A Commuter’s Challenge in Suburban Philadelphia
Every morning, Midge, a healthcare worker, embarks on her daily
journey from the quiet streets of Pottstown in Montgomery County
to the bustling corridors of the Hospital of the University of
Pennsylvania in Philadelphia. Her commute is more than just a physical
journey—it’s a daily ordeal, wrestling with the infrequent and
unreliable bus service that connects the suburban sprawl to the urban
core. On a good day, Midge waits 30 minutes for Bus 93; on a bad day,
the wait can exceed an hour. She must then transfer to the Norristown
High Speed Line, extending her total morning commute to over 2.5
hours—five times longer than Philadelphia’s average commute time. This
inconsistency isn’t just a personal inconvenience; it’s a stark
reflection of the broader issues of transit inequities that plague many
in the suburbs, where buses are few and far between despite the pressing
need.
Midge’s story is not unique in Greater Philadelphia—a region where
58.2 percent of public transit users are women and 66.4 percent are
people of color. These individuals predominantly populate essential
sectors like healthcare, education, and social assistance which employs
25.6 percent of suburban county workers who depend on public
transportation. Despite playing critical roles in their communities,
these workers earn median annual earnings approximately $7,673 below the
regional average. This economic disparity is exacerbated by the transit
challenges they face, where the gap in accessibility and frequency of
service widens the divide between different socioeconomic groups.
Additionally, a significant portion of the workforce, about 35%, lives
below the poverty line, heavily relying on this patchwork public
transport system that struggles to meet their daily needs.
The Importance of Transit for Suburban Communities
Midge’s daily commute sheds light on a more significant issue: the
critical role of public transportation in providing access to essential
services and economic opportunities, especially in suburban communities.
Studies highlight a robust negative correlation between unemployment
rates and proximity to transit access. In New York City, neighborhoods
with some but limited transit access experienced a significantly higher
unemployment rate (12.6%) compared to areas with robust transit options
(8.1%).
This lack of transit access limits physical and economic mobility,
contributing to income inequality and higher public assistance
dependency.
Moreover, reliable public transportation is pivotal for healthcare
access. The National Health Interview Survey (2002) estimated that 3.6
million people miss non-emergency medical appointments annually due to
transportation issues. This issue disproportionately affects communities
of color, who rely more heavily on public transportation compared to
white populations. Midge’s commute is not just a matter of
convenience; it’s about accessing crucial healthcare services that
manage chronic conditions and provide necessary treatments.
Transportation also plays a fundamental role in educational access.
The “geography of opportunity” significantly shapes educational outcomes
through accessible transportation, enabling children and young people to
reach schools and participate in extracurricular activities. A study in
Minneapolis found that high school students with access to an unlimited
bus and rail pass attended school more regularly and achieved higher
GPAs by 0.23 than students without a pass, highlighting the
importance of reliable transit in educational attainment.
Using the latest SEPTA General Transit Feed Specification (GTFS)
data, it
reveals that a staggering 80% of SEPTA’s trips are made by bus,
showcasing the critical role of bus transit in Philadelphia’s
transportation network. This statistic underlines the heavy reliance on
buses across the city, not just in suburban areas.
# Import GTFS data
stops <- read.csv("data/google_bus/stops.txt", header = TRUE, sep = ",")
stop_times <- read.csv("data/google_bus/stop_times.txt", header = TRUE, sep = ",")
trips <- read.csv("data/google_bus/trips.txt", header = TRUE, sep = ",")
shapes <- read.csv("data/google_bus/shapes.txt", header = TRUE, sep = ",")
routes <- read.csv("data/google_bus/routes.txt", header = TRUE, sep = ",")
calendar <- read.csv("data/google_bus/calendar.txt", header = TRUE, sep = ",")
calendar_dates <- read.csv("data/google_bus/calendar_dates.txt", header = TRUE, sep = ",")
# Import Swiftly data
swiftly <- st_read("data/SwiftlyShapes/geoJSONs/SEPTASurface_HighResSpeed_v2.json")
# Join stop_times and trips, from now on dat will be our main data set
dat <- left_join(stop_times, trips, by = "trip_id")
# join dat and routes
dat <- left_join(dat, routes, by = "route_id")
#determine route_type
dat <- dat %>%
mutate(mode = if_else(route_type == 0, "Trolley", ifelse(route_type == 1, "Metro", ifelse(route_type == 3, "Bus", "Trolleybus"))))
# Mode share (not ridership)
dat_trip_by_mode <- dat %>%
group_by(mode) %>%
summarise(mode_count = n(), .groups = 'drop') %>%
mutate(total_count = sum(mode_count),
mode_share = round(mode_count/sum(mode_count)*100, digits = 2)) %>%
ungroup()
# # Plot mode share using ggplot2 and the custom palette
ggplot(dat_trip_by_mode, aes(x = mode, y = mode_share, fill = mode)) +
geom_bar(stat = "identity", width = 0.75) +
scale_fill_manual(values = bus_revolution_palette(length(unique(dat_trip_by_mode$mode)))) +
geom_text(aes(label = paste0(mode_share, "% (", mode_count, " trips)")),
vjust = -0.5, color = "black", size = 2.5) +
labs(title = "Mode Share by Transit Type",
x = "Mode",
y = "Mode Share (%)",
fill = "Mode",
caption = "Source: SEPTA GTFS Data 2024") +
theme_minimal() +
theme(legend.position = "right",
plot.title = element_text(hjust = 0.5))

#
# # total trip bus & trolley bus 1.980.505, total observations 2.026.677
#
# ggplot() +
# # Add service period background rectangles with reduced alpha for subtlety
# geom_rect(data = service_periods, aes(xmin = start_hour, xmax = end_hour, ymin = 0, ymax = max(hourly_trips$number_of_trips), fill = peak_category), alpha = 0.2) +
# # Add the line plot for weekday trips with adjusted point sizes
# geom_line(data = hourly_trips %>% filter(final_day_type == "Weekday"), aes(x = hour, y = number_of_trips), color = "#F2AE2E", size = 1) +
# geom_point(data = hourly_trips %>% filter(final_day_type == "Weekday"), aes(x = hour, y = number_of_trips), color = "#26A699", size = 3) +
# # Add the line plot for weekend trips with a new color for better differentiation
# geom_line(data = hourly_trips %>% filter(final_day_type == "Weekend"), aes(x = hour, y = number_of_trips), color = "#0072B2", size = 1) +
# geom_point(data = hourly_trips %>% filter(final_day_type == "Weekend"), aes(x = hour, y = number_of_trips), color = "#D55E00", size = 3) +
# # Define scales and labels with appropriate adjustments
# scale_x_continuous(breaks = 0:23) +
# scale_y_continuous(labels = scales::comma) +
# scale_fill_manual(values = service_period_colors) +
# scale_color_manual(values = c("Weekday" = "#F2AE2E", "Weekend" = "#0072B2")) +
# labs(title = "Number of Trips by Hour with Service Periods",
# x = "Hour of Day",
# y = "Number of Trips",
# fill = "Service Period",
# color = "Day Type") +
# theme_minimal() +
# theme(legend.position = "bottom",
# plot.title = element_text(hjust = 0.5))
# CREATE LINE GRAPH OF TRIPS BY SERVICE PERIODS
# Function to normalize times greater than 24:00:00. Important step: check the stop_times$arrival_time and departure_time values if it's greater than 24:00
normalize_time <- function(time_str) {
time_parts <- strsplit(time_str, ":")[[1]]
hours <- as.numeric(time_parts[1])
minutes <- as.numeric(time_parts[2])
seconds <- as.numeric(time_parts[3])
if (hours >= 24) {
hours <- hours - 24
time_str <- sprintf("%02d:%02d:%02d", hours, minutes, seconds)
}
return(time_str)
}
#identify peak_pm category
dat <- dat %>%
mutate(departure_time = sapply(departure_time, normalize_time), # departure_time's normalized
departure_time = lubridate::hms(departure_time),
hour = hour(departure_time), # Extract hour component for easier condition checking
peak_category = if_else(hour >= 4 & hour < 6, "Early Morning",
if_else(hour >= 6 & hour < 9, "AM Peak",
if_else(hour >= 9 & hour < 15, "Mid Day",
if_else(hour >= 15 & hour < 18, "PM Peak",
if_else(hour >= 18 & hour < 22, "Evening",
ifelse(hour >= 22 & hour < 24, "Late Night", "Owl")))))))
# # Check if there are any NA values in the 'departure_time' column
# summarise(dat,
# na_count = sum(is.na(departure_time)), #Count NA values
# total_rows = n(), # Total number of rows for context
# percentage_na = na_count / total_rows * 100 # Percentage of NA values
# )
durations <- c("Owl" = 4, "Early Morning" = 2, "AM Peak" = 3, "Mid Day" = 6, "PM Peak" = 3, "Evening" = 4, "Late Night" = 2)
dat_service_period <- dat %>%
filter(mode %in% c("Bus", "Trolleybus", "Trolley")) %>%
group_by(peak_category)%>%
summarise(peak_count = n(), .groups = 'drop') %>%
mutate(total_count = sum(peak_count),
peak_share = round(peak_count/sum(peak_count)*100, digits = 2)) %>%
arrange(factor(peak_category, levels = c("Owl", "Early Morning", "AM Peak", "Mid Day", "PM Peak", "Evening", "Late Night"))) %>%
ungroup()
# Create a data frame for service periods
service_periods <- data.frame(
peak_category = c("Owl", "Early Morning", "AM Peak", "Mid Day", "PM Peak", "Evening", "Late Night"),
start_hour = c(0, 4, 6, 9, 15, 18, 22),
end_hour = c(4, 6, 9, 15, 18, 22, 24)
)
# CREATE BAR CHART OF TRIPS BY SERVICE TYPES
# Ensure 'calendar' has 'day_type' defined
calendar <- calendar %>%
mutate(
day_type = case_when(
monday == 1 & tuesday == 1 & wednesday == 1 & thursday == 1 & friday == 1 & saturday == 0 & sunday == 0 ~ "Weekday",
(saturday == 1 | sunday == 1) ~ "Weekend",
TRUE ~ "irregular"
)
)
# Calendar_dates includes 'service_id', 'date', and 'exception_type'
# Ensure 'calendar_dates' has 'day_type' defined based on the date
calendar_dates <- calendar_dates %>%
filter(exception_type == 1) %>% #we only need exception_type == 1, those added to the service
mutate(
date = ymd(date), # Convert date format if necessary
day_of_week = wday(date, label = TRUE, week_start = 1),
day_type = case_when(
day_of_week %in% c("Mon", "Tue", "Wed", "Thu", "Fri") ~ "Weekday", # Monday to Friday
TRUE ~ "Weekend" # Saturday and Sunday
)
)
# Join calendar_dates with calendar
calendar_joined <- calendar_dates %>%
full_join(calendar, by = "service_id", suffix = c(".dates", ".cal")) %>%
mutate(
final_day_type = case_when(
# Use calendar_dates' day_type if exception_type indicates added service
exception_type == 1 & day_type.dates == "Weekday" ~ "Weekday",
exception_type == 1 & day_type.dates == "Weekend" ~ "Weekend",
# Default to calendar's day_type where there's no specific exception noted
TRUE ~ day_type.cal
)
) %>%
select(service_id, final_day_type) %>%
group_by(service_id, final_day_type) %>%
summarise(count = n(), .groups = 'drop') %>%
arrange(service_id, desc(count)) %>%
distinct(service_id, .keep_all = TRUE) %>% # Make sure no double day types for service ID
select(-count)
dat <- dat %>%
left_join(calendar_joined, by = "service_id")
# SET UP STOPS CATEGORY. This step is crucial as we'll use stops information and join them for each kind of maps
# Convert stops data to sf object
stops <- stops %>%
st_as_sf(coords = c("stop_lon", "stop_lat"), crs = 4326, remove = FALSE)
# Load PA and SEPTA region map for base map
PA <- st_read("data/PaCounty2024_05.geojson")
SEPTA_region_map <- PA[PA$COUNTY_NAM %in% c("MONTGOMERY", "BUCKS", "PHILADELPHIA", "DELAWARE", "CHESTER"), ] %>%
select(PA_CTY_COD, COUNTY_NAM, FIPS_COUNT)
# Load Center City boundary
center_city <- st_read("data/20240708_CenterCity/CenterCity.shp")
# Ensure all datasets are in the same CRS
SEPTA_region_map <- st_transform(SEPTA_region_map, crs = st_crs(stops))
center_city <- st_transform(center_city, crs = st_crs(stops))
# Perform the spatial intersection for county
stops <- stops %>%
st_join(SEPTA_region_map, left = TRUE, join = st_intersects) %>%
rename(county = COUNTY_NAM) %>%
mutate(center_city = st_within(stops, center_city, sparse = FALSE))%>%
mutate(center_city = rowSums(center_city) > 0) # Convert logical matrix to vector
# Categorize the stops
stops <- stops %>%
mutate(category = case_when(
county == "PHILADELPHIA" & center_city == TRUE ~ "PHILADELPHIA-Center_City",
county == "PHILADELPHIA" & center_city == FALSE ~ "PHILADELPHIA-Not_Center_City",
TRUE ~ county
)) %>%
select(-"center_city")
# SET UP HOURLY AVERAGE TRIP DATA FOR EACH BUS STOP
dat_trip_count_hr <- dat %>%
filter(mode %in% c("Bus", "Trolleybus", "Trolley")) %>%
group_by(stop_id, mode, final_day_type) %>%
summarise(trip_count = n(),
All_Routes = paste(unique(route_id), collapse = ", "),
.groups = 'drop') %>%
mutate(avg_trip_hr = round(trip_count/24)) %>%
mutate(log_avg_trip_hr = round(log1p(avg_trip_hr), digits = 0)) %>%
mutate(max_freq = ifelse(avg_trip_hr >= 12, "5 MAX",
ifelse (avg_trip_hr >= 6, "10 MAX",
ifelse (avg_trip_hr >= 4, "15 MAX",
ifelse(avg_trip_hr >= 2, "30 MAX", "60 MAX")))))
dat_trip_count_hr <- left_join(dat_trip_count_hr, stops, by = "stop_id")
dat_trip_count_hr <- st_as_sf(dat_trip_count_hr, coords = c("stop_lon", "stop_lat"), crs = 4326, remove = FALSE)
# Assuming 'county' is the column with the county information
dat_trip_count_hr <- dat_trip_count_hr %>%
mutate(category = if_else(county == "PHILADELPHIA", "urban", "suburban"))
# Simplify the max frequency into two categories
dat_trip_count_hr <- dat_trip_count_hr %>%
mutate(simplified_freq = case_when(
max_freq %in% c("5 MAX", "10 MAX", "15 MAX") ~ "15 minutes or less",
TRUE ~ "More than 15 minutes"
))
# Remove rows where 'category' is NA
dat_trip_count_hr <- dat_trip_count_hr %>% filter(!is.na(category))
# sum(dat_trip_count_hr$trip_count) #1980505 <- Always make sure you retain the number of observation
Unraveling the Disparities in Bus Service Efficiency
The disparities in bus service efficiency between urban and suburban
areas are starkly highlighted by frequency data. In suburban areas, the
majority of bus stops suffer from infrequent services. This contrasts
sharply with urban areas, where bus stops generally provide more
frequent services. These differences underline significant inequities in
transit accessibility, impacting daily commuters like Midge who rely
heavily on these services.
In the following leaflet map, we illustrate these disparities. You’ll
see that bus stops in suburban areas predominantly have longer waiting
times, exceeding 15 minutes,
whereas urban stops typically has waiting time under 15 minutes, demonstrating more
frequent services. This visual representation emphasizes the urgent need
for targeted improvements in suburban transit systems to bridge the gap
and enhance overall service reliability and efficiency.
# SET UP AVERAGE TRIP DATA PER SERVICE PERIOD FOR EACH BUS STOP
dat_trip_count_prd <- dat %>%
filter(mode %in% c("Bus", "Trolleybus", "Trolley")) %>%
group_by(stop_id, peak_category, mode, final_day_type) %>%
summarise(trip_count = n(),
All_Routes = paste(unique(route_id), collapse = ", "),
.groups = 'drop') %>%
mutate(
hours = durations[peak_category],
avg_trip_hr = round(trip_count / hours)
) %>%
select(-hours) %>%
mutate(log_avg_trip_hr = round(log1p(avg_trip_hr), digits = 0)) %>%
mutate(max_freq = ifelse(avg_trip_hr >= 12, "5 MAX",
ifelse (avg_trip_hr >= 6, "10 MAX",
ifelse (avg_trip_hr >= 4, "15 MAX",
ifelse(avg_trip_hr >= 2, "30 MAX", "60 MAX")))))
dat_trip_count_prd <- left_join(dat_trip_count_prd, stops, by = "stop_id")
dat_trip_count_prd <- st_as_sf(dat_trip_count_prd, coords = c("stop_lon", "stop_lat"), crs = 4326, remove = FALSE)
# sum(dat_trip_count_prd$trip_count) #1980505 <- Always make sure you retain the number of observation
SEPTA_region_map <- st_transform(SEPTA_region_map, st_crs(dat_trip_count_hr))
# Define color palette for simplified frequency using the bus revolution colors
pal <- colorFactor(c("#A6123A", "#655BA6"), domain = c("15 minutes or less", "More than 15 minutes"))
# Create the leaflet map
m_avg_trip_hr <- leaflet() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addPolygons(data = SEPTA_region_map, color = "black", weight = 1, fill = FALSE) %>%
addCircleMarkers(
data = dat_trip_count_hr %>% filter(final_day_type == "Weekday" & !is.na(category)),
group = ~category, # Group data based on urban or suburban
lng = ~stop_lon,
lat = ~stop_lat,
color = ~pal(simplified_freq), # Color based on simplified frequency
radius = 1,
opacity = 0.8,
popup = ~paste0("<b>Stop ID:</b> ", stop_id, "<br>",
"<b>Stop Name:</b> ", stop_name, "<br>",
"<b>Avg Buses/Hr:</b> ", avg_trip_hr, "<br>",
"<b>Max Frequency:</b> ", simplified_freq, "<br>",
"<b>All Routes:</b> ", All_Routes)
) %>%
addLayersControl(
overlayGroups = c("urban", "suburban"),
options = layersControlOptions(collapsed = FALSE)
) %>%
addControl(html = "<div style='background-color: white; padding: 5px;'><strong>Source:</strong> SEPTA GTFS Data 2024</div>", position = "bottomleft")
# Display the map
m_avg_trip_hr
Midge’s daily challenge with inconsistent suburban bus service
reflects broader transit inequities between urban and suburban settings.
This disparity is exemplified by the operational inefficiencies of
suburban routes, highlighted by data indicating these buses frequently
fall within the lowest 15th percentile for service performance. This low
percentile indicates prolonged wait times and unreliable
schedules—factors contributing to higher operational costs and reduced
reliability compared to more efficient urban counterparts.
Suburban buses, like the routes
Midge uses, often suffer due to lower ridership densities and less
optimized route planning, as reflected in the significant number of
suburban routes like Routes 118, 129, and 90 underperforming in the 15th
percentile. These routes’ inefficiencies starkly contrast with the
robust transit systems in urban areas, underscoring a critical gap in
transit equity and efficiency that demands innovative solutions.
route_evaluation <- read.csv("data/route_evaluation_report_2019.csv", sep = ";")
# Convert Cost.per.Passenger and Passengers.per.Revenue.Hour into proper numeric columns
route_evaluation$Cost.per.Passenger <- as.numeric(gsub("[$,]", "", route_evaluation$Cost.per.Passenger))
route_evaluation$Passengers.per.Revenue.Hour <- as.numeric(route_evaluation$Passengers.per.Revenue.Hour)
# Calculate 15th percentile for Passengers and 85th percentile for Cost (due to reversed axis)
passenger_15th <- quantile(route_evaluation$Passengers.per.Revenue.Hour, probs = 0.15, na.rm = TRUE)
cost_85th <- quantile(route_evaluation$Cost.per.Passenger, probs = 0.85, na.rm = TRUE)
# Define color palette for the types of buses
route_colors <- c("City Bus" = "#A6123A", "Suburban Bus" = "#655BA6")
pal <- colorFactor(route_colors, domain = unique(route_evaluation$Type))
# Create the ggplot
p <- ggplot(route_evaluation, aes(x = Passengers.per.Revenue.Hour, y = Cost.per.Passenger, color = Type, text = paste("Route:", Route, "<br>Passengers per Revenue Hour:", Passengers.per.Revenue.Hour, "<br>Cost per Passenger:", Cost.per.Passenger, "<br>Type:", Type))) +
annotate("rect", xmin = 0, xmax = passenger_15th, ymin = max(route_evaluation$Cost.per.Passenger), ymax = cost_85th, fill = "lightcoral", alpha = 0.2) +
geom_vline(xintercept = passenger_15th, linetype = "dashed", color = "grey") +
geom_hline(yintercept = cost_85th, linetype = "dashed", color = "grey") +
geom_point() +
labs(title = "Performance of SEPTA City Bus and Suburban Bus",
x = "Passengers per Revenue Hour",
y = "Cost per Passenger",
caption = "Source: SEPTA FY 2019 Report") +
scale_color_manual(values = route_colors) +
scale_y_reverse(breaks = seq(0, max(route_evaluation$Cost.per.Passenger, na.rm = TRUE), by = 1),
labels = dollar_format(prefix = "$", suffix = "", accuracy = 0.01)) +
scale_x_continuous(breaks = seq(0, max(route_evaluation$Passengers.per.Revenue.Hour, na.rm = TRUE), by = 10)) +
theme_minimal() +
theme(legend.position = "none") +
annotate("text", x = passenger_15th / 2, y = 6.5, label = "15th percentile", size = 3, color = "black", alpha = 0.5)
# Convert to plotly for an interactive plot with detailed hover information
p_plotly <- ggplotly(p, tooltip = "text")
# Display the interactive plot
p_plotly
Although microtransit has been proposed as an alternative to address
these inefficiencies by offering more adaptable and potentially
efficient services in lower-density areas, its effectiveness remains
questionable. For example, AC Transit’s experiment in Oakland to replace
fixed routes with microtransit resulted in a cost per passenger that
more than doubled, highlighting the challenges of implementing such
services effectively.
This data illustrates that while microtransit is often touted as a
modern solution for declining ridership, it generally does not perform
as efficiently as traditional fixed-route services. The core efficiency
of fixed-route transit comes from its ability to consolidate riders
along a predictable path, minimizing deviations and ensuring consistent
travel times. In contrast, microtransit’s on-demand nature can lead to
significant inefficiencies, with routes constantly changing to
accommodate individual pickup requests, leading to increased travel
times and operational costs.
Given these challenges, it might be more prudent to explore other
alternatives, such as deploying smaller, fixed-route minibusses during
peak hours to enhance connectivity and manage crowding more effectively.
This approach could leverage the lower operational costs of smaller
vehicles while maintaining the structured efficiency of fixed-route
transit, potentially offering a more sustainable solution to the
suburban transit woes that Midge and countless others face daily.
Impact and Innovation: Enhancing Suburban Bus Services
While the raw data illuminates the service disparities, the true
depth of this issue is best captured through the lived experiences of
suburban commuters like Midge. Personal stories reveal the broader human
impact: missed opportunities, prolonged workdays, and diminished family
life due to infrequent bus services. This qualitative insight paints a
vivid picture of the daily challenges and underscores the urgency for
targeted improvements.
SEPTA’s ongoing “Bus Revolution” project aims to modernize and
enhance bus services, promising updated routes and improved frequencies
that haven’t been revised since the 1960s. While the initiative seeks to
reduce headways to a maximum of 30 minutes even in the most remote
suburban areas, it has faced delays and criticism, particularly
concerning its potential to disproportionately impact low-income
neighborhoods. This tension highlights the complex interplay between
improving service efficiency and addressing community concerns of
gentrification.
As we conclude our exploration of suburban bus transit disparities in
Philadelphia, the compelling narratives of daily commuters, underpinned
by robust SEPTA data, paint a clear picture of the challenges and the
urgent need for systemic improvements. The “Bus Revolution” project,
while a promising step toward enhancing bus frequencies and updating
decades-old routes, also highlights the delicate balance required to
improve service efficiency without exacerbating social inequities.
Embracing innovative solutions and fostering community engagement in
transit planning are crucial. By committing to both technological
upgrades and equitable service distribution, SEPTA can ensure that every
commuter, regardless of where they live, has reliable and timely access
to public transit. This not only improves individual daily experiences
but also supports broader goals of economic mobility and sustainable
urban development.
As stakeholders, we are called upon to support these initiatives,
advocate for transparent and inclusive planning processes, and ensure
that the voices of all commuters, especially those most affected like
Midge, are heard and addressed in the pursuit of a truly connected and
equitable transit system.
LS0tCnRpdGxlOiAiV2FpdGluZyBmb3IgQ2hhbmdlOiBUaGUgVXJnZW50IE5lZWQgZm9yIEVxdWl0YWJsZSBCdXMgU2VydmljZXMgaW4gU3VidXJiYW4gUGhpbGFkZWxwaGlhIgphdXRob3I6ICJSZWd5IFNlcHRpYW4iCmRhdGU6ICIyMDI0LTExLTMwIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiAiaGlkZSIKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBjYWNoZSA9IEZBTFNFKQoKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoc2YpCmxpYnJhcnkodGlkeXRyYW5zaXQpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGhtcykKbGlicmFyeSh0aWR5cikKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeSh3aykKbGlicmFyeShsZWFmbGV0KQpsaWJyYXJ5KGxlYWZsZXQuZXh0cmFzKQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkodmlyaWRpc0xpdGUpCmxpYnJhcnkoaHRtbHdpZGdldHMpCmxpYnJhcnkoaHRtbHRvb2xzKQpsaWJyYXJ5KGxlYWZsZXQuZXh0cmFzKQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoc2hpbnkpCmxpYnJhcnkod2Vic2hvdDIpCmxpYnJhcnkobWFnaWNrKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShyZWFkcikKCiMgRGVmaW5lIHRoZSBjb2xvciBjb2RlcwpidXNfcmV2b2x1dGlvbl9jb2xvcnMgPC0gYygiI0E2MTIzQSIsICIjNjU1QkE2IiwgIiMyNkE2OTkiLCAiI0YyQUUyRSIsICIjRjJFNUQ1IikKCiMgQ3JlYXRlIGEgY3VzdG9tIHBhbGV0dGUgZnVuY3Rpb24KYnVzX3Jldm9sdXRpb25fcGFsZXR0ZSA8LSBmdW5jdGlvbihuKSB7CiAgY29sb3JSYW1wUGFsZXR0ZShidXNfcmV2b2x1dGlvbl9jb2xvcnMpKG4pCn0KCndvcmtkaXIgPC0gIn4vT25lRHJpdmUgLSBQZW5uTzM2NS8wM19VTklWRVJTSVRZX09GX1BFTk5TWUxWQU5JQS1NQ1BfMjAyNS8wNF9GQUxMXzI0LzAzX01VU0FfNjk1MV9Db21tdW5pY2F0aW9uX2luX1VyYmFuX1NwYXRpYWxfQW5hbHl0aWNzL01VU0EtNjMxMF9Bc3NpZ25tZW50LTIvTVVTQS02MzEwX0Fzc2lnbm1lbnQtMiIgIyBDaGFuZ2UgdGhlIGRpcmVjdG9yeQpzZXR3ZCh3b3JrZGlyKQpgYGAKCiMjIyBBIENvbW11dGVyJ3MgQ2hhbGxlbmdlIGluIFN1YnVyYmFuIFBoaWxhZGVscGhpYSAgCgpFdmVyeSBtb3JuaW5nLCBNaWRnZSwgYSBoZWFsdGhjYXJlIHdvcmtlciwgZW1iYXJrcyBvbiBoZXIgZGFpbHkgam91cm5leSBmcm9tIHRoZSBxdWlldCBzdHJlZXRzIG9mIFBvdHRzdG93blteMV0gaW4gTW9udGdvbWVyeSBDb3VudHkgdG8gdGhlIGJ1c3RsaW5nIGNvcnJpZG9ycyBvZiB0aGUgSG9zcGl0YWwgb2YgdGhlIFVuaXZlcnNpdHkgb2YgUGVubnN5bHZhbmlhIGluIFBoaWxhZGVscGhpYS4gSGVyIGNvbW11dGUgaXMgbW9yZSB0aGFuIGp1c3QgYSBwaHlzaWNhbCBqb3VybmV54oCUaXTigJlzIGEgZGFpbHkgb3JkZWFsLCB3cmVzdGxpbmcgd2l0aCB0aGUgaW5mcmVxdWVudCBhbmQgdW5yZWxpYWJsZSBidXMgc2VydmljZSB0aGF0IGNvbm5lY3RzIHRoZSBzdWJ1cmJhbiBzcHJhd2wgdG8gdGhlIHVyYmFuIGNvcmUuIE9uIGEgZ29vZCBkYXksIE1pZGdlIHdhaXRzIDMwIG1pbnV0ZXMgZm9yIEJ1cyA5Mzsgb24gYSBiYWQgZGF5LCB0aGUgd2FpdCBjYW4gZXhjZWVkIGFuIGhvdXIuIFNoZSBtdXN0IHRoZW4gdHJhbnNmZXIgdG8gdGhlIE5vcnJpc3Rvd24gSGlnaCBTcGVlZCBMaW5lLCBleHRlbmRpbmcgaGVyIHRvdGFsIG1vcm5pbmcgY29tbXV0ZSB0byBvdmVyIDIuNSBob3Vyc+KAlGZpdmUgdGltZXMgbG9uZ2VyIHRoYW4gUGhpbGFkZWxwaGlhJ3MgYXZlcmFnZSBjb21tdXRlIHRpbWUuW14yXSBUaGlzIGluY29uc2lzdGVuY3kgaXNuJ3QganVzdCBhIHBlcnNvbmFsIGluY29udmVuaWVuY2U7IGl0J3MgYSBzdGFyayByZWZsZWN0aW9uIG9mIHRoZSBicm9hZGVyIGlzc3VlcyBvZiB0cmFuc2l0IGluZXF1aXRpZXMgdGhhdCBwbGFndWUgbWFueSBpbiB0aGUgc3VidXJicywgd2hlcmUgYnVzZXMgYXJlIGZldyBhbmQgZmFyIGJldHdlZW4gZGVzcGl0ZSB0aGUgcHJlc3NpbmcgbmVlZC4KCk1pZGdlJ3Mgc3RvcnkgaXMgbm90IHVuaXF1ZSBpbiBHcmVhdGVyIFBoaWxhZGVscGhpYeKAlGEgcmVnaW9uIHdoZXJlIDU4LjIgcGVyY2VudCBvZiBwdWJsaWMgdHJhbnNpdCB1c2VycyBhcmUgd29tZW4gYW5kIDY2LjQgcGVyY2VudCBhcmUgcGVvcGxlIG9mIGNvbG9yLiBUaGVzZSBpbmRpdmlkdWFscyBwcmVkb21pbmFudGx5IHBvcHVsYXRlIGVzc2VudGlhbCBzZWN0b3JzIGxpa2UgaGVhbHRoY2FyZSwgZWR1Y2F0aW9uLCBhbmQgc29jaWFsIGFzc2lzdGFuY2Ugd2hpY2ggZW1wbG95cyAyNS42IHBlcmNlbnQgb2Ygc3VidXJiYW4gY291bnR5IHdvcmtlcnMgd2hvIGRlcGVuZCBvbiBwdWJsaWMgdHJhbnNwb3J0YXRpb24uIERlc3BpdGUgcGxheWluZyBjcml0aWNhbCByb2xlcyBpbiB0aGVpciBjb21tdW5pdGllcywgdGhlc2Ugd29ya2VycyBlYXJuIG1lZGlhbiBhbm51YWwgZWFybmluZ3MgYXBwcm94aW1hdGVseSAkNyw2NzMgYmVsb3cgdGhlIHJlZ2lvbmFsIGF2ZXJhZ2UuIFRoaXMgZWNvbm9taWMgZGlzcGFyaXR5IGlzIGV4YWNlcmJhdGVkIGJ5IHRoZSB0cmFuc2l0IGNoYWxsZW5nZXMgdGhleSBmYWNlLCB3aGVyZSB0aGUgZ2FwIGluIGFjY2Vzc2liaWxpdHkgYW5kIGZyZXF1ZW5jeSBvZiBzZXJ2aWNlIHdpZGVucyB0aGUgZGl2aWRlIGJldHdlZW4gZGlmZmVyZW50IHNvY2lvZWNvbm9taWMgZ3JvdXBzLiBBZGRpdGlvbmFsbHksIGEgc2lnbmlmaWNhbnQgcG9ydGlvbiBvZiB0aGUgd29ya2ZvcmNlLCBhYm91dCAzNSUsIGxpdmVzIGJlbG93IHRoZSBwb3ZlcnR5IGxpbmUsIGhlYXZpbHkgcmVseWluZyBvbiB0aGlzIHBhdGNod29yayBwdWJsaWMgdHJhbnNwb3J0IHN5c3RlbSB0aGF0IHN0cnVnZ2xlcyB0byBtZWV0IHRoZWlyIGRhaWx5IG5lZWRzLlteM10gCgpbXjFdOiBbV0hZWTogVHJhY2luZyBNb250Y2/igJlzIGRlY2FkZXMtbG9uZyBzaGlmdCBmcm9tIEdPUCBzdHJvbmdob2xkIHRvIGJvb24gZm9yIEJpZGVuXShodHRwczovL3doeXkub3JnL2FydGljbGVzL3RyYWNpbmctbW9udGNvcy1kZWNhZGVzLWxvbmctc2hpZnQtZnJvbS1nb3Atc3Ryb25naG9sZC10by1ib29uLWZvci1iaWRlbi8pClteMl06IFtUaGUgUGhpbGFkZWxwaGlhIElucXVpcmVyOiBQaGlsbHkgY29tbXV0ZXMgYXJlIGdldHRpbmcgc2xpZ2h0bHkgcXVpY2tlciwgYnV0IHRoZXnigJlyZSBhbW9uZyB0aGUgbG9uZ2VzdCBpbiB0aGUgVS5TLl0oaHR0cHM6Ly93d3cuaW5xdWlyZXIuY29tL3RyYW5zcG9ydGF0aW9uL3BoaWxhZGVscGhpYS1jb21tdXRlLXRpbWUtbG9uZ2VzdC10cmFuc2l0LTIwMjQxMDEwLmh0bWwjbG9hZGVkKQpbXjNdOiBbRWNvbm9teSBMZWFndWU6IEdyZWF0ZXIgUGhpbGFkZWxwaGlh4oCZcyBQdWJsaWMgVHJhbnNwb3J0YXRpb24gYW5kIENPVklELTE5IOKAkyBQQVJUIDJdKGh0dHBzOi8vd3d3LmVjb25vbXlsZWFndWUub3JnL3Jlc291cmNlcy9ncmVhdGVyLXBoaWxhZGVscGhpYXMtcHVibGljLXRyYW5zcG9ydGF0aW9uLWFuZC1jb3ZpZC0xOS1wYXJ0LTIjKQoKIyMjIFRoZSBJbXBvcnRhbmNlIG9mIFRyYW5zaXQgZm9yIFN1YnVyYmFuIENvbW11bml0aWVzICAKCk1pZGdl4oCZcyBkYWlseSBjb21tdXRlIHNoZWRzIGxpZ2h0IG9uIGEgbW9yZSBzaWduaWZpY2FudCBpc3N1ZTogdGhlIGNyaXRpY2FsIHJvbGUgb2YgcHVibGljIHRyYW5zcG9ydGF0aW9uIGluIHByb3ZpZGluZyBhY2Nlc3MgdG8gZXNzZW50aWFsIHNlcnZpY2VzIGFuZCBlY29ub21pYyBvcHBvcnR1bml0aWVzLCBlc3BlY2lhbGx5IGluIHN1YnVyYmFuIGNvbW11bml0aWVzLiBTdHVkaWVzIGhpZ2hsaWdodCBhIHJvYnVzdCBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHVuZW1wbG95bWVudCByYXRlcyBhbmQgcHJveGltaXR5IHRvIHRyYW5zaXQgYWNjZXNzLiBJbiBOZXcgWW9yayBDaXR5LCBuZWlnaGJvcmhvb2RzIHdpdGggc29tZSBidXQgbGltaXRlZCB0cmFuc2l0IGFjY2VzcyBleHBlcmllbmNlZCBhIHNpZ25pZmljYW50bHkgaGlnaGVyIHVuZW1wbG95bWVudCByYXRlICgxMi42JSkgY29tcGFyZWQgdG8gYXJlYXMgd2l0aCByb2J1c3QgdHJhbnNpdCBvcHRpb25zICg4LjElKS4gW140XSBUaGlzIGxhY2sgb2YgdHJhbnNpdCBhY2Nlc3MgbGltaXRzIHBoeXNpY2FsIGFuZCBlY29ub21pYyBtb2JpbGl0eSwgY29udHJpYnV0aW5nIHRvIGluY29tZSBpbmVxdWFsaXR5IGFuZCBoaWdoZXIgcHVibGljIGFzc2lzdGFuY2UgZGVwZW5kZW5jeS4KCk1vcmVvdmVyLCByZWxpYWJsZSBwdWJsaWMgdHJhbnNwb3J0YXRpb24gaXMgcGl2b3RhbCBmb3IgaGVhbHRoY2FyZSBhY2Nlc3MuIFRoZSBOYXRpb25hbCBIZWFsdGggSW50ZXJ2aWV3IFN1cnZleSAoMjAwMikgZXN0aW1hdGVkIHRoYXQgMy42IG1pbGxpb24gcGVvcGxlIG1pc3Mgbm9uLWVtZXJnZW5jeSBtZWRpY2FsIGFwcG9pbnRtZW50cyBhbm51YWxseSBkdWUgdG8gdHJhbnNwb3J0YXRpb24gaXNzdWVzLiBUaGlzIGlzc3VlIGRpc3Byb3BvcnRpb25hdGVseSBhZmZlY3RzIGNvbW11bml0aWVzIG9mIGNvbG9yLCB3aG8gcmVseSBtb3JlIGhlYXZpbHkgb24gcHVibGljIHRyYW5zcG9ydGF0aW9uIGNvbXBhcmVkIHRvIHdoaXRlIHBvcHVsYXRpb25zLiBbXjVdIE1pZGdl4oCZcyBjb21tdXRlIGlzIG5vdCBqdXN0IGEgbWF0dGVyIG9mIGNvbnZlbmllbmNlOyBpdOKAmXMgYWJvdXQgYWNjZXNzaW5nIGNydWNpYWwgaGVhbHRoY2FyZSBzZXJ2aWNlcyB0aGF0IG1hbmFnZSBjaHJvbmljIGNvbmRpdGlvbnMgYW5kIHByb3ZpZGUgbmVjZXNzYXJ5IHRyZWF0bWVudHMuCgpUcmFuc3BvcnRhdGlvbiBhbHNvIHBsYXlzIGEgZnVuZGFtZW50YWwgcm9sZSBpbiBlZHVjYXRpb25hbCBhY2Nlc3MuIFRoZSAiZ2VvZ3JhcGh5IG9mIG9wcG9ydHVuaXR5IiBzaWduaWZpY2FudGx5IHNoYXBlcyBlZHVjYXRpb25hbCBvdXRjb21lcyB0aHJvdWdoIGFjY2Vzc2libGUgdHJhbnNwb3J0YXRpb24sIGVuYWJsaW5nIGNoaWxkcmVuIGFuZCB5b3VuZyBwZW9wbGUgdG8gcmVhY2ggc2Nob29scyBhbmQgcGFydGljaXBhdGUgaW4gZXh0cmFjdXJyaWN1bGFyIGFjdGl2aXRpZXMuW142XSBBIHN0dWR5IGluIE1pbm5lYXBvbGlzIGZvdW5kIHRoYXQgaGlnaCBzY2hvb2wgc3R1ZGVudHMgd2l0aCBhY2Nlc3MgdG8gYW4gdW5saW1pdGVkIGJ1cyBhbmQgcmFpbCBwYXNzIGF0dGVuZGVkIHNjaG9vbCBtb3JlIHJlZ3VsYXJseSBhbmQgYWNoaWV2ZWQgaGlnaGVyIEdQQXMgYnkgMC4yMyB0aGFuIHN0dWRlbnRzIHdpdGhvdXQgYSBwYXNzLCBbXjddIGhpZ2hsaWdodGluZyB0aGUgaW1wb3J0YW5jZSBvZiByZWxpYWJsZSB0cmFuc2l0IGluIGVkdWNhdGlvbmFsIGF0dGFpbm1lbnQuCgpVc2luZyB0aGUgbGF0ZXN0IFNFUFRBIEdlbmVyYWwgVHJhbnNpdCBGZWVkIFNwZWNpZmljYXRpb24gKEdURlMpIGRhdGFbXjhdLCBpdCByZXZlYWxzIHRoYXQgYSBzdGFnZ2VyaW5nIDgwJSBvZiBTRVBUQSdzIHRyaXBzIGFyZSBtYWRlIGJ5IGJ1cywgc2hvd2Nhc2luZyB0aGUgY3JpdGljYWwgcm9sZSBvZiBidXMgdHJhbnNpdCBpbiBQaGlsYWRlbHBoaWHigJlzIHRyYW5zcG9ydGF0aW9uIG5ldHdvcmsuIFRoaXMgc3RhdGlzdGljIHVuZGVybGluZXMgdGhlIGhlYXZ5IHJlbGlhbmNlIG9uIGJ1c2VzIGFjcm9zcyB0aGUgY2l0eSwgbm90IGp1c3QgaW4gc3VidXJiYW4gYXJlYXMuIAoKW140XTogW0thdWZtYW4gYW5kIGNvbGxlYWd1ZXMgMjAxNV0oaHR0cHM6Ly93YWduZXIubnl1LmVkdS9maWxlcy9mYWN1bHR5L3B1YmxpY2F0aW9ucy9Kb2JBY2Nlc3NOb3YyMDE1LnBkZikKW141XTogW1dhbGxhY2UgZXQgYWwuIDIwMTVdKGh0dHBzOi8vam91cm5hbHMuc2FnZXB1Yi5jb20vZG9pL2Ficy8xMC4xMTc3LzAzNjExOTgxMDUxOTI0MDAxMTApClteNl06IFtWaW5jZW50IGV0IGFsLiAyMDE0XShodHRwczovL2VyaWMuZWQuZ292Lz9pZD1FRDU1ODU0MikKW143XTogW0ZhbiBhbmQgRGFzIDIwMTVdKGh0dHBzOi8vY29uc2VydmFuY3kudW1uLmVkdS9pdGVtcy81ZDk5ODk2OC1hYWZlLTRiZjAtOTJkOC1lNWRhNTczMmY0ZjcpClteOF06IFtTRVBUQSBHVEZTXShodHRwczovL3d3dzMuc2VwdGEub3JnL2RldmVsb3Blci9ndGZzX3B1YmxpYy56aXApCgoKYGBge3IgaW1wb3J0IGd0ZnMsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUUsIHJlc3VsdHMgPSAnaGlkZSd9CiMgSW1wb3J0IEdURlMgZGF0YQpzdG9wcyA8LSByZWFkLmNzdigiZGF0YS9nb29nbGVfYnVzL3N0b3BzLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIikKc3RvcF90aW1lcyA8LSByZWFkLmNzdigiZGF0YS9nb29nbGVfYnVzL3N0b3BfdGltZXMudHh0IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiKQp0cmlwcyA8LSByZWFkLmNzdigiZGF0YS9nb29nbGVfYnVzL3RyaXBzLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIikKc2hhcGVzIDwtIHJlYWQuY3N2KCJkYXRhL2dvb2dsZV9idXMvc2hhcGVzLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIikKcm91dGVzIDwtIHJlYWQuY3N2KCJkYXRhL2dvb2dsZV9idXMvcm91dGVzLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIikKY2FsZW5kYXIgPC0gcmVhZC5jc3YoImRhdGEvZ29vZ2xlX2J1cy9jYWxlbmRhci50eHQiLCBoZWFkZXIgPSBUUlVFLCBzZXAgPSAiLCIpCmNhbGVuZGFyX2RhdGVzIDwtIHJlYWQuY3N2KCJkYXRhL2dvb2dsZV9idXMvY2FsZW5kYXJfZGF0ZXMudHh0IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiKQoKIyBJbXBvcnQgU3dpZnRseSBkYXRhCnN3aWZ0bHkgPC0gc3RfcmVhZCgiZGF0YS9Td2lmdGx5U2hhcGVzL2dlb0pTT05zL1NFUFRBU3VyZmFjZV9IaWdoUmVzU3BlZWRfdjIuanNvbiIpCgpgYGAKCmBgYHtyIHRvdGFsIHRyaXAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUV9CiMgSm9pbiBzdG9wX3RpbWVzIGFuZCB0cmlwcywgZnJvbSBub3cgb24gZGF0IHdpbGwgYmUgb3VyIG1haW4gZGF0YSBzZXQKZGF0IDwtIGxlZnRfam9pbihzdG9wX3RpbWVzLCB0cmlwcywgYnkgPSAidHJpcF9pZCIpCgojIGpvaW4gZGF0IGFuZCByb3V0ZXMKZGF0IDwtIGxlZnRfam9pbihkYXQsIHJvdXRlcywgYnkgPSAicm91dGVfaWQiKQoKI2RldGVybWluZSByb3V0ZV90eXBlCmRhdCA8LSBkYXQgJT4lCiAgbXV0YXRlKG1vZGUgPSBpZl9lbHNlKHJvdXRlX3R5cGUgPT0gMCwgIlRyb2xsZXkiLCBpZmVsc2Uocm91dGVfdHlwZSA9PSAxLCAiTWV0cm8iLCBpZmVsc2Uocm91dGVfdHlwZSA9PSAzLCAiQnVzIiwgIlRyb2xsZXlidXMiKSkpKQoKIyBNb2RlIHNoYXJlIChub3QgcmlkZXJzaGlwKQpkYXRfdHJpcF9ieV9tb2RlIDwtIGRhdCAlPiUKICBncm91cF9ieShtb2RlKSAlPiUKICBzdW1tYXJpc2UobW9kZV9jb3VudCA9IG4oKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgbXV0YXRlKHRvdGFsX2NvdW50ID0gc3VtKG1vZGVfY291bnQpLAogICAgICAgICBtb2RlX3NoYXJlID0gcm91bmQobW9kZV9jb3VudC9zdW0obW9kZV9jb3VudCkqMTAwLCBkaWdpdHMgPSAyKSkgJT4lCiAgdW5ncm91cCgpIAogIAojICMgUGxvdCBtb2RlIHNoYXJlIHVzaW5nIGdncGxvdDIgYW5kIHRoZSBjdXN0b20gcGFsZXR0ZQpnZ3Bsb3QoZGF0X3RyaXBfYnlfbW9kZSwgYWVzKHggPSBtb2RlLCB5ID0gbW9kZV9zaGFyZSwgZmlsbCA9IG1vZGUpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC43NSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGJ1c19yZXZvbHV0aW9uX3BhbGV0dGUobGVuZ3RoKHVuaXF1ZShkYXRfdHJpcF9ieV9tb2RlJG1vZGUpKSkpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKG1vZGVfc2hhcmUsICIlICgiLCBtb2RlX2NvdW50LCAiIHRyaXBzKSIpKSwKICAgICAgICAgICAgdmp1c3QgPSAtMC41LCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyLjUpICsKICBsYWJzKHRpdGxlID0gIk1vZGUgU2hhcmUgYnkgVHJhbnNpdCBUeXBlIiwKICAgICAgIHggPSAiTW9kZSIsCiAgICAgICB5ID0gIk1vZGUgU2hhcmUgKCUpIiwKICAgICAgIGZpbGwgPSAiTW9kZSIsCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogU0VQVEEgR1RGUyBEYXRhIDIwMjQiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQojIAojICMgdG90YWwgdHJpcCBidXMgJiB0cm9sbGV5IGJ1cyAxLjk4MC41MDUsIHRvdGFsIG9ic2VydmF0aW9ucyAyLjAyNi42NzcKIyAKIyBnZ3Bsb3QoKSArCiMgICAjIEFkZCBzZXJ2aWNlIHBlcmlvZCBiYWNrZ3JvdW5kIHJlY3RhbmdsZXMgd2l0aCByZWR1Y2VkIGFscGhhIGZvciBzdWJ0bGV0eQojICAgZ2VvbV9yZWN0KGRhdGEgPSBzZXJ2aWNlX3BlcmlvZHMsIGFlcyh4bWluID0gc3RhcnRfaG91ciwgeG1heCA9IGVuZF9ob3VyLCB5bWluID0gMCwgeW1heCA9IG1heChob3VybHlfdHJpcHMkbnVtYmVyX29mX3RyaXBzKSwgZmlsbCA9IHBlYWtfY2F0ZWdvcnkpLCBhbHBoYSA9IDAuMikgKwojICAgIyBBZGQgdGhlIGxpbmUgcGxvdCBmb3Igd2Vla2RheSB0cmlwcyB3aXRoIGFkanVzdGVkIHBvaW50IHNpemVzCiMgICBnZW9tX2xpbmUoZGF0YSA9IGhvdXJseV90cmlwcyAlPiUgZmlsdGVyKGZpbmFsX2RheV90eXBlID09ICJXZWVrZGF5IiksIGFlcyh4ID0gaG91ciwgeSA9IG51bWJlcl9vZl90cmlwcyksIGNvbG9yID0gIiNGMkFFMkUiLCBzaXplID0gMSkgKwojICAgZ2VvbV9wb2ludChkYXRhID0gaG91cmx5X3RyaXBzICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtkYXkiKSwgYWVzKHggPSBob3VyLCB5ID0gbnVtYmVyX29mX3RyaXBzKSwgY29sb3IgPSAiIzI2QTY5OSIsIHNpemUgPSAzKSArCiMgICAjIEFkZCB0aGUgbGluZSBwbG90IGZvciB3ZWVrZW5kIHRyaXBzIHdpdGggYSBuZXcgY29sb3IgZm9yIGJldHRlciBkaWZmZXJlbnRpYXRpb24KIyAgIGdlb21fbGluZShkYXRhID0gaG91cmx5X3RyaXBzICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtlbmQiKSwgYWVzKHggPSBob3VyLCB5ID0gbnVtYmVyX29mX3RyaXBzKSwgY29sb3IgPSAiIzAwNzJCMiIsIHNpemUgPSAxKSArCiMgICBnZW9tX3BvaW50KGRhdGEgPSBob3VybHlfdHJpcHMgJT4lIGZpbHRlcihmaW5hbF9kYXlfdHlwZSA9PSAiV2Vla2VuZCIpLCBhZXMoeCA9IGhvdXIsIHkgPSBudW1iZXJfb2ZfdHJpcHMpLCBjb2xvciA9ICIjRDU1RTAwIiwgc2l6ZSA9IDMpICsKIyAgICMgRGVmaW5lIHNjYWxlcyBhbmQgbGFiZWxzIHdpdGggYXBwcm9wcmlhdGUgYWRqdXN0bWVudHMKIyAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAwOjIzKSArCiMgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKwojICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gc2VydmljZV9wZXJpb2RfY29sb3JzKSArCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiV2Vla2RheSIgPSAiI0YyQUUyRSIsICJXZWVrZW5kIiA9ICIjMDA3MkIyIikpICsKIyAgIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIFRyaXBzIGJ5IEhvdXIgd2l0aCBTZXJ2aWNlIFBlcmlvZHMiLAojICAgICAgICB4ID0gIkhvdXIgb2YgRGF5IiwKIyAgICAgICAgeSA9ICJOdW1iZXIgb2YgVHJpcHMiLAojICAgICAgICBmaWxsID0gIlNlcnZpY2UgUGVyaW9kIiwKIyAgICAgICAgY29sb3IgPSAiRGF5IFR5cGUiKSArCiMgICB0aGVtZV9taW5pbWFsKCkgKwojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiMgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgpgYGB7ciBwZWFrIHRpbWUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUUsIHJlc3VsdHMgPSAnaGlkZSd9CiMgQ1JFQVRFIExJTkUgR1JBUEggT0YgVFJJUFMgQlkgU0VSVklDRSBQRVJJT0RTCgojIEZ1bmN0aW9uIHRvIG5vcm1hbGl6ZSB0aW1lcyBncmVhdGVyIHRoYW4gMjQ6MDA6MDAuIEltcG9ydGFudCBzdGVwOiBjaGVjayB0aGUgc3RvcF90aW1lcyRhcnJpdmFsX3RpbWUgYW5kIGRlcGFydHVyZV90aW1lIHZhbHVlcyBpZiBpdCdzIGdyZWF0ZXIgdGhhbiAyNDowMCAKbm9ybWFsaXplX3RpbWUgPC0gZnVuY3Rpb24odGltZV9zdHIpIHsKICB0aW1lX3BhcnRzIDwtIHN0cnNwbGl0KHRpbWVfc3RyLCAiOiIpW1sxXV0KICBob3VycyA8LSBhcy5udW1lcmljKHRpbWVfcGFydHNbMV0pCiAgbWludXRlcyA8LSBhcy5udW1lcmljKHRpbWVfcGFydHNbMl0pCiAgc2Vjb25kcyA8LSBhcy5udW1lcmljKHRpbWVfcGFydHNbM10pCiAgCiAgaWYgKGhvdXJzID49IDI0KSB7CiAgICBob3VycyA8LSBob3VycyAtIDI0CiAgICB0aW1lX3N0ciA8LSBzcHJpbnRmKCIlMDJkOiUwMmQ6JTAyZCIsIGhvdXJzLCBtaW51dGVzLCBzZWNvbmRzKQogIH0KICAKICByZXR1cm4odGltZV9zdHIpCn0KCiNpZGVudGlmeSBwZWFrX3BtIGNhdGVnb3J5IApkYXQgPC0gZGF0ICU+JQogIG11dGF0ZShkZXBhcnR1cmVfdGltZSA9IHNhcHBseShkZXBhcnR1cmVfdGltZSwgbm9ybWFsaXplX3RpbWUpLCAjIGRlcGFydHVyZV90aW1lJ3Mgbm9ybWFsaXplZAogICAgICAgICBkZXBhcnR1cmVfdGltZSA9IGx1YnJpZGF0ZTo6aG1zKGRlcGFydHVyZV90aW1lKSwKICAgICAgICAgaG91ciA9IGhvdXIoZGVwYXJ0dXJlX3RpbWUpLCAgIyBFeHRyYWN0IGhvdXIgY29tcG9uZW50IGZvciBlYXNpZXIgY29uZGl0aW9uIGNoZWNraW5nCiAgICAgICAgIHBlYWtfY2F0ZWdvcnkgPSBpZl9lbHNlKGhvdXIgPj0gNCAmIGhvdXIgPCA2LCAiRWFybHkgTW9ybmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoaG91ciA+PSA2ICYgaG91ciA8IDksICJBTSBQZWFrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGhvdXIgPj0gOSAmIGhvdXIgPCAxNSwgIk1pZCBEYXkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShob3VyID49IDE1ICYgaG91ciA8IDE4LCAiUE0gUGVhayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoaG91ciA+PSAxOCAmIGhvdXIgPCAyMiwgIkV2ZW5pbmciLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoaG91ciA+PSAyMiAmIGhvdXIgPCAyNCwgIkxhdGUgTmlnaHQiLCAiT3dsIikpKSkpKSkgCgojICMgQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBOQSB2YWx1ZXMgaW4gdGhlICdkZXBhcnR1cmVfdGltZScgY29sdW1uCiMgc3VtbWFyaXNlKGRhdCwKIyAgICAgbmFfY291bnQgPSBzdW0oaXMubmEoZGVwYXJ0dXJlX3RpbWUpKSwgI0NvdW50IE5BIHZhbHVlcwojICAgICB0b3RhbF9yb3dzID0gbigpLCAgIyBUb3RhbCBudW1iZXIgb2Ygcm93cyBmb3IgY29udGV4dAojICAgICBwZXJjZW50YWdlX25hID0gbmFfY291bnQgLyB0b3RhbF9yb3dzICogMTAwICAjIFBlcmNlbnRhZ2Ugb2YgTkEgdmFsdWVzCiMgICApCgpkdXJhdGlvbnMgPC0gYygiT3dsIiA9IDQsICJFYXJseSBNb3JuaW5nIiA9IDIsICJBTSBQZWFrIiA9IDMsICJNaWQgRGF5IiA9IDYsICJQTSBQZWFrIiA9IDMsICJFdmVuaW5nIiA9IDQsICJMYXRlIE5pZ2h0IiA9IDIpCgpkYXRfc2VydmljZV9wZXJpb2QgPC0gZGF0ICU+JQogIGZpbHRlcihtb2RlICVpbiUgYygiQnVzIiwgIlRyb2xsZXlidXMiLCAiVHJvbGxleSIpKSAlPiUKICBncm91cF9ieShwZWFrX2NhdGVnb3J5KSU+JQogIHN1bW1hcmlzZShwZWFrX2NvdW50ID0gbigpLCAuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUKICBtdXRhdGUodG90YWxfY291bnQgPSBzdW0ocGVha19jb3VudCksCiAgICAgICAgIHBlYWtfc2hhcmUgPSByb3VuZChwZWFrX2NvdW50L3N1bShwZWFrX2NvdW50KSoxMDAsIGRpZ2l0cyA9IDIpKSAlPiUKICBhcnJhbmdlKGZhY3RvcihwZWFrX2NhdGVnb3J5LCBsZXZlbHMgPSBjKCJPd2wiLCAiRWFybHkgTW9ybmluZyIsICJBTSBQZWFrIiwgIk1pZCBEYXkiLCAiUE0gUGVhayIsICJFdmVuaW5nIiwgIkxhdGUgTmlnaHQiKSkpICU+JQogIHVuZ3JvdXAoKQoKIyBDcmVhdGUgYSBkYXRhIGZyYW1lIGZvciBzZXJ2aWNlIHBlcmlvZHMKc2VydmljZV9wZXJpb2RzIDwtIGRhdGEuZnJhbWUoCiAgcGVha19jYXRlZ29yeSA9IGMoIk93bCIsICJFYXJseSBNb3JuaW5nIiwgIkFNIFBlYWsiLCAiTWlkIERheSIsICJQTSBQZWFrIiwgIkV2ZW5pbmciLCAiTGF0ZSBOaWdodCIpLAogIHN0YXJ0X2hvdXIgPSBjKDAsIDQsIDYsIDksIDE1LCAxOCwgMjIpLAogIGVuZF9ob3VyID0gYyg0LCA2LCA5LCAxNSwgMTgsIDIyLCAyNCkKKQoKIyBDUkVBVEUgQkFSIENIQVJUIE9GIFRSSVBTIEJZIFNFUlZJQ0UgVFlQRVMKCiMgRW5zdXJlICdjYWxlbmRhcicgaGFzICdkYXlfdHlwZScgZGVmaW5lZApjYWxlbmRhciA8LSBjYWxlbmRhciAlPiUKICBtdXRhdGUoCiAgICBkYXlfdHlwZSA9IGNhc2Vfd2hlbigKICAgICAgbW9uZGF5ID09IDEgJiB0dWVzZGF5ID09IDEgJiB3ZWRuZXNkYXkgPT0gMSAmIHRodXJzZGF5ID09IDEgJiBmcmlkYXkgPT0gMSAmIHNhdHVyZGF5ID09IDAgJiBzdW5kYXkgPT0gMCB+ICJXZWVrZGF5IiwKICAgICAgKHNhdHVyZGF5ID09IDEgfCBzdW5kYXkgPT0gMSkgfiAiV2Vla2VuZCIsCiAgICAgIFRSVUUgfiAiaXJyZWd1bGFyIgogICAgKQogICkKCiMgQ2FsZW5kYXJfZGF0ZXMgaW5jbHVkZXMgJ3NlcnZpY2VfaWQnLCAnZGF0ZScsIGFuZCAnZXhjZXB0aW9uX3R5cGUnCiMgRW5zdXJlICdjYWxlbmRhcl9kYXRlcycgaGFzICdkYXlfdHlwZScgZGVmaW5lZCBiYXNlZCBvbiB0aGUgZGF0ZQpjYWxlbmRhcl9kYXRlcyA8LSBjYWxlbmRhcl9kYXRlcyAlPiUKICBmaWx0ZXIoZXhjZXB0aW9uX3R5cGUgPT0gMSkgJT4lICN3ZSBvbmx5IG5lZWQgZXhjZXB0aW9uX3R5cGUgPT0gMSwgdGhvc2UgYWRkZWQgdG8gdGhlIHNlcnZpY2UKICBtdXRhdGUoCiAgICBkYXRlID0geW1kKGRhdGUpLCAgIyBDb252ZXJ0IGRhdGUgZm9ybWF0IGlmIG5lY2Vzc2FyeQogICAgZGF5X29mX3dlZWsgPSB3ZGF5KGRhdGUsIGxhYmVsID0gVFJVRSwgd2Vla19zdGFydCA9IDEpLAogICAgZGF5X3R5cGUgPSBjYXNlX3doZW4oCiAgICAgIGRheV9vZl93ZWVrICVpbiUgYygiTW9uIiwgIlR1ZSIsICJXZWQiLCAiVGh1IiwgIkZyaSIpIH4gIldlZWtkYXkiLCAgIyBNb25kYXkgdG8gRnJpZGF5CiAgICAgIFRSVUUgfiAiV2Vla2VuZCIgICMgU2F0dXJkYXkgYW5kIFN1bmRheQogICAgKQogICkKCiMgSm9pbiBjYWxlbmRhcl9kYXRlcyB3aXRoIGNhbGVuZGFyCmNhbGVuZGFyX2pvaW5lZCA8LSBjYWxlbmRhcl9kYXRlcyAlPiUKICBmdWxsX2pvaW4oY2FsZW5kYXIsIGJ5ID0gInNlcnZpY2VfaWQiLCBzdWZmaXggPSBjKCIuZGF0ZXMiLCAiLmNhbCIpKSAlPiUKICBtdXRhdGUoCiAgICBmaW5hbF9kYXlfdHlwZSA9IGNhc2Vfd2hlbigKICAgICAgIyBVc2UgY2FsZW5kYXJfZGF0ZXMnIGRheV90eXBlIGlmIGV4Y2VwdGlvbl90eXBlIGluZGljYXRlcyBhZGRlZCBzZXJ2aWNlCiAgICAgIGV4Y2VwdGlvbl90eXBlID09IDEgJiBkYXlfdHlwZS5kYXRlcyA9PSAiV2Vla2RheSIgfiAiV2Vla2RheSIsCiAgICAgIGV4Y2VwdGlvbl90eXBlID09IDEgJiBkYXlfdHlwZS5kYXRlcyA9PSAiV2Vla2VuZCIgfiAiV2Vla2VuZCIsCiAgICAgICMgRGVmYXVsdCB0byBjYWxlbmRhcidzIGRheV90eXBlIHdoZXJlIHRoZXJlJ3Mgbm8gc3BlY2lmaWMgZXhjZXB0aW9uIG5vdGVkCiAgICAgIFRSVUUgfiBkYXlfdHlwZS5jYWwKICAgICkKICApICU+JQogIHNlbGVjdChzZXJ2aWNlX2lkLCBmaW5hbF9kYXlfdHlwZSkgJT4lCiAgZ3JvdXBfYnkoc2VydmljZV9pZCwgZmluYWxfZGF5X3R5cGUpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgYXJyYW5nZShzZXJ2aWNlX2lkLCBkZXNjKGNvdW50KSkgJT4lCiAgZGlzdGluY3Qoc2VydmljZV9pZCwgLmtlZXBfYWxsID0gVFJVRSkgJT4lICMgTWFrZSBzdXJlIG5vIGRvdWJsZSBkYXkgdHlwZXMgZm9yIHNlcnZpY2UgSUQKICBzZWxlY3QoLWNvdW50KQogIApkYXQgPC0gZGF0ICU+JQogIGxlZnRfam9pbihjYWxlbmRhcl9qb2luZWQsIGJ5ID0gInNlcnZpY2VfaWQiKQoKYGBgCgpgYGB7ciBjYWxlbmRhciwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KZGF0X3NlcnZpY2VfdHlwZSA8LSBkYXQgJT4lCiAgZmlsdGVyKG1vZGUgJWluJSBjKCJCdXMiLCAiVHJvbGxleWJ1cyIsICJUcm9sbGV5IikpICU+JQogIGdyb3VwX2J5KGZpbmFsX2RheV90eXBlKSU+JQogIHN1bW1hcmlzZShkYXlfdHlwZV9jb3VudCA9IG4oKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgbXV0YXRlKHRvdGFsX2NvdW50ID0gc3VtKGRheV90eXBlX2NvdW50KSwKICAgICAgICAgcGVha19zaGFyZSA9IHJvdW5kKGRheV90eXBlX2NvdW50L3N1bShkYXlfdHlwZV9jb3VudCkqMTAwLCBkaWdpdHMgPSAyKSkgJT4lCiAgYXJyYW5nZShmYWN0b3IoZmluYWxfZGF5X3R5cGUsIGxldmVscyA9IGMoIldlZWtkYXkiLCAiV2Vla2VuZCIpKSkgJT4lCiAgdW5ncm91cCgpCgojIFN1bW1hcml6ZSBkYXRhIHRvIGdldCB0aGUgbnVtYmVyIG9mIHRyaXBzIHBlciBob3VyCmhvdXJseV90cmlwcyA8LSBkYXQgJT4lCiAgZmlsdGVyKG1vZGUgJWluJSBjKCJCdXMiLCAiVHJvbGxleWJ1cyIsICJUcm9sbGV5IikpICU+JQogIGdyb3VwX2J5KGhvdXIsIGZpbmFsX2RheV90eXBlKSAlPiUKICBzdW1tYXJpc2UobnVtYmVyX29mX3RyaXBzID0gbigpKQoKIyBEZWZpbmUgYSBjdXN0b20gcGFsZXR0ZSBmb3IgdGhlIHNlcnZpY2UgcGVyaW9kcwpzZXJ2aWNlX3BlcmlvZF9jb2xvcnMgPC0gYygKICAiT3dsIiA9ICIjRTVFNUU1IiwKICAiRWFybHkgTW9ybmluZyIgPSAiI0M1RTBCNCIsCiAgIkFNIFBlYWsiID0gIiNBOUQwOEUiLAogICJNaWQgRGF5IiA9ICIjRkZEOTY2IiwKICAiUE0gUGVhayIgPSAiI0Y0QjA4NCIsCiAgIkV2ZW5pbmciID0gIiNENUE2QkQiLAogICJMYXRlIE5pZ2h0IiA9ICIjQTRDMkY0IgopCgojICMgUGxvdCB0aGUgY29tYmluZWQgZ3JhcGgKIyBnZ3Bsb3QoKSArCiMgICAjIEFkZCBzZXJ2aWNlIHBlcmlvZCBiYWNrZ3JvdW5kIHJlY3RhbmdsZXMKIyAgIGdlb21fcmVjdChkYXRhID0gc2VydmljZV9wZXJpb2RzLCBhZXMoeG1pbiA9IHN0YXJ0X2hvdXIsIHhtYXggPSBlbmRfaG91ciwgeW1pbiA9IDAsIHltYXggPSBtYXgoaG91cmx5X3RyaXBzJG51bWJlcl9vZl90cmlwcyksIGZpbGwgPSBwZWFrX2NhdGVnb3J5KSwgYWxwaGEgPSAwLjMpICsKIyAgICMgQWRkIHRoZSBsaW5lIHBsb3QgZm9yIHdlZWtkYXkgdHJpcHMKIyAgIGdlb21fbGluZShkYXRhID0gaG91cmx5X3RyaXBzICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtkYXkiKSwgYWVzKHggPSBob3VyLCB5ID0gbnVtYmVyX29mX3RyaXBzKSwgY29sb3IgPSAiI0YyQUUyRSIsIHNpemUgPSAxKSArCiMgICBnZW9tX3BvaW50KGRhdGEgPSBob3VybHlfdHJpcHMgJT4lIGZpbHRlcihmaW5hbF9kYXlfdHlwZSA9PSAiV2Vla2RheSIpLCBhZXMoeCA9IGhvdXIsIHkgPSBudW1iZXJfb2ZfdHJpcHMpLCBjb2xvciA9ICIjMjZBNjk5Iiwgc2l6ZSA9IDIpICsKIyAgICMgQWRkIHRoZSBsaW5lIHBsb3QgZm9yIHdlZWtlbmQgdHJpcHMKIyAgIGdlb21fbGluZShkYXRhID0gaG91cmx5X3RyaXBzICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtlbmQiKSwgYWVzKHggPSBob3VyLCB5ID0gbnVtYmVyX29mX3RyaXBzKSwgY29sb3IgPSAiI0E2MTIzQSIsIHNpemUgPSAxKSArCiMgICBnZW9tX3BvaW50KGRhdGEgPSBob3VybHlfdHJpcHMgJT4lIGZpbHRlcihmaW5hbF9kYXlfdHlwZSA9PSAiV2Vla2VuZCIpLCBhZXMoeCA9IGhvdXIsIHkgPSBudW1iZXJfb2ZfdHJpcHMpLCBjb2xvciA9ICIjMjZBNjk5Iiwgc2l6ZSA9IDIpICsKIyAgICMgRGVmaW5lIHNjYWxlcyBhbmQgbGFiZWxzCiMgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMDoyMykgKwojICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSArCiMgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzZXJ2aWNlX3BlcmlvZF9jb2xvcnMpICsKIyAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJXZWVrZGF5IiA9ICIjRjJBRTJFIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2Vla2VuZCIgPSAiI0E2MTIzQSIpKSArCiMgICBsYWJzKHRpdGxlID0gIk51bWJlciBvZiBUcmlwcyBieSBIb3VyIHdpdGggU2VydmljZSBQZXJpb2RzIiwKIyAgICAgICAgeCA9ICJIb3VyIG9mIERheSIsCiMgICAgICAgIHkgPSAiTnVtYmVyIG9mIFRyaXBzIiwKIyAgICAgICAgZmlsbCA9ICJTZXJ2aWNlIFBlcmlvZCIsCiMgICAgICAgIGNvbG9yID0gIkRheSBUeXBlIikgKwojICAgdGhlbWVfbWluaW1hbCgpICsKIyAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAojICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCiAgCmBgYAoKCmBgYHtyIHNldCB1cCBzdG9wcyBjYXRlZ29yeSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9VFJVRSwgcmVzdWx0cyA9ICdoaWRlJ30KIyBTRVQgVVAgU1RPUFMgQ0FURUdPUlkuIFRoaXMgc3RlcCBpcyBjcnVjaWFsIGFzIHdlJ2xsIHVzZSBzdG9wcyBpbmZvcm1hdGlvbiBhbmQgam9pbiB0aGVtIGZvciBlYWNoIGtpbmQgb2YgbWFwcyAKCiMgQ29udmVydCBzdG9wcyBkYXRhIHRvIHNmIG9iamVjdApzdG9wcyA8LSBzdG9wcyAlPiUKICBzdF9hc19zZihjb29yZHMgPSBjKCJzdG9wX2xvbiIsICJzdG9wX2xhdCIpLCBjcnMgPSA0MzI2LCByZW1vdmUgPSBGQUxTRSkKCiMgTG9hZCBQQSBhbmQgU0VQVEEgcmVnaW9uIG1hcCBmb3IgYmFzZSBtYXAKUEEgPC0gc3RfcmVhZCgiZGF0YS9QYUNvdW50eTIwMjRfMDUuZ2VvanNvbiIpClNFUFRBX3JlZ2lvbl9tYXAgPC0gUEFbUEEkQ09VTlRZX05BTSAlaW4lIGMoIk1PTlRHT01FUlkiLCAiQlVDS1MiLCAiUEhJTEFERUxQSElBIiwgIkRFTEFXQVJFIiwgIkNIRVNURVIiKSwgXSAlPiUKICBzZWxlY3QoUEFfQ1RZX0NPRCwgQ09VTlRZX05BTSwgRklQU19DT1VOVCkKCiMgTG9hZCBDZW50ZXIgQ2l0eSBib3VuZGFyeQpjZW50ZXJfY2l0eSA8LSBzdF9yZWFkKCJkYXRhLzIwMjQwNzA4X0NlbnRlckNpdHkvQ2VudGVyQ2l0eS5zaHAiKQoKIyBFbnN1cmUgYWxsIGRhdGFzZXRzIGFyZSBpbiB0aGUgc2FtZSBDUlMKU0VQVEFfcmVnaW9uX21hcCA8LSBzdF90cmFuc2Zvcm0oU0VQVEFfcmVnaW9uX21hcCwgY3JzID0gc3RfY3JzKHN0b3BzKSkKY2VudGVyX2NpdHkgPC0gc3RfdHJhbnNmb3JtKGNlbnRlcl9jaXR5LCBjcnMgPSBzdF9jcnMoc3RvcHMpKQoKIyBQZXJmb3JtIHRoZSBzcGF0aWFsIGludGVyc2VjdGlvbiBmb3IgY291bnR5CnN0b3BzIDwtIHN0b3BzICU+JQogIHN0X2pvaW4oU0VQVEFfcmVnaW9uX21hcCwgbGVmdCA9IFRSVUUsIGpvaW4gPSBzdF9pbnRlcnNlY3RzKSAlPiUKICByZW5hbWUoY291bnR5ID0gQ09VTlRZX05BTSkgJT4lCiAgbXV0YXRlKGNlbnRlcl9jaXR5ID0gc3Rfd2l0aGluKHN0b3BzLCBjZW50ZXJfY2l0eSwgc3BhcnNlID0gRkFMU0UpKSU+JQogIG11dGF0ZShjZW50ZXJfY2l0eSA9IHJvd1N1bXMoY2VudGVyX2NpdHkpID4gMCkgICMgQ29udmVydCBsb2dpY2FsIG1hdHJpeCB0byB2ZWN0b3IKCiMgQ2F0ZWdvcml6ZSB0aGUgc3RvcHMKc3RvcHMgPC0gc3RvcHMgJT4lCiAgbXV0YXRlKGNhdGVnb3J5ID0gY2FzZV93aGVuKAogICAgY291bnR5ID09ICJQSElMQURFTFBISUEiICYgY2VudGVyX2NpdHkgPT0gVFJVRSB+ICJQSElMQURFTFBISUEtQ2VudGVyX0NpdHkiLAogICAgY291bnR5ID09ICJQSElMQURFTFBISUEiICYgY2VudGVyX2NpdHkgPT0gRkFMU0UgfiAiUEhJTEFERUxQSElBLU5vdF9DZW50ZXJfQ2l0eSIsCiAgICBUUlVFIH4gY291bnR5CiAgKSkgJT4lCiAgc2VsZWN0KC0iY2VudGVyX2NpdHkiKQogIApgYGAKCmBgYHtyIGhvdXJseSBzdG9wIGRhdGEsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPVRSVUUsIHJlc3VsdHMgPSAnaGlkZSd9CiMgU0VUIFVQIEhPVVJMWSBBVkVSQUdFIFRSSVAgREFUQSBGT1IgRUFDSCBCVVMgU1RPUAoKZGF0X3RyaXBfY291bnRfaHIgPC0gZGF0ICU+JQogIGZpbHRlcihtb2RlICVpbiUgYygiQnVzIiwgIlRyb2xsZXlidXMiLCAiVHJvbGxleSIpKSAlPiUKICBncm91cF9ieShzdG9wX2lkLCBtb2RlLCBmaW5hbF9kYXlfdHlwZSkgJT4lCiAgc3VtbWFyaXNlKHRyaXBfY291bnQgPSBuKCksIAogICAgICAgICAgICBBbGxfUm91dGVzID0gcGFzdGUodW5pcXVlKHJvdXRlX2lkKSwgY29sbGFwc2UgPSAiLCAiKSwKICAgICAgICAgICAgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgbXV0YXRlKGF2Z190cmlwX2hyID0gcm91bmQodHJpcF9jb3VudC8yNCkpICU+JQogIG11dGF0ZShsb2dfYXZnX3RyaXBfaHIgPSByb3VuZChsb2cxcChhdmdfdHJpcF9ociksIGRpZ2l0cyA9IDApKSAlPiUKICBtdXRhdGUobWF4X2ZyZXEgPSBpZmVsc2UoYXZnX3RyaXBfaHIgPj0gMTIsICI1IE1BWCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoYXZnX3RyaXBfaHIgPj0gNiwgIjEwIE1BWCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSAoYXZnX3RyaXBfaHIgPj0gNCwgIjE1IE1BWCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoYXZnX3RyaXBfaHIgPj0gMiwgIjMwIE1BWCIsICI2MCBNQVgiKSkpKSkKCmRhdF90cmlwX2NvdW50X2hyIDwtIGxlZnRfam9pbihkYXRfdHJpcF9jb3VudF9ociwgc3RvcHMsIGJ5ID0gInN0b3BfaWQiKQoKZGF0X3RyaXBfY291bnRfaHIgPC0gc3RfYXNfc2YoZGF0X3RyaXBfY291bnRfaHIsIGNvb3JkcyA9IGMoInN0b3BfbG9uIiwgInN0b3BfbGF0IiksIGNycyA9IDQzMjYsIHJlbW92ZSA9IEZBTFNFKQoKIyBBc3N1bWluZyAnY291bnR5JyBpcyB0aGUgY29sdW1uIHdpdGggdGhlIGNvdW50eSBpbmZvcm1hdGlvbgpkYXRfdHJpcF9jb3VudF9ociA8LSBkYXRfdHJpcF9jb3VudF9ociAlPiUKICBtdXRhdGUoY2F0ZWdvcnkgPSBpZl9lbHNlKGNvdW50eSA9PSAiUEhJTEFERUxQSElBIiwgInVyYmFuIiwgInN1YnVyYmFuIikpCgojIFNpbXBsaWZ5IHRoZSBtYXggZnJlcXVlbmN5IGludG8gdHdvIGNhdGVnb3JpZXMKZGF0X3RyaXBfY291bnRfaHIgPC0gZGF0X3RyaXBfY291bnRfaHIgJT4lCiAgbXV0YXRlKHNpbXBsaWZpZWRfZnJlcSA9IGNhc2Vfd2hlbigKICAgIG1heF9mcmVxICVpbiUgYygiNSBNQVgiLCAiMTAgTUFYIiwgIjE1IE1BWCIpIH4gIjE1IG1pbnV0ZXMgb3IgbGVzcyIsCiAgICBUUlVFIH4gIk1vcmUgdGhhbiAxNSBtaW51dGVzIgogICkpCgojIFJlbW92ZSByb3dzIHdoZXJlICdjYXRlZ29yeScgaXMgTkEKZGF0X3RyaXBfY291bnRfaHIgPC0gZGF0X3RyaXBfY291bnRfaHIgJT4lIGZpbHRlcighaXMubmEoY2F0ZWdvcnkpKQoKIyBzdW0oZGF0X3RyaXBfY291bnRfaHIkdHJpcF9jb3VudCkgIzE5ODA1MDUgPC0gQWx3YXlzIG1ha2Ugc3VyZSB5b3UgcmV0YWluIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb24KCmBgYAoKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KZ2dwbG90KGRhdF90cmlwX2J5X21vZGUsIGFlcyh4ID0gbW9kZSwgeSA9IG1vZGVfc2hhcmUsIGZpbGwgPSBtb2RlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNzUpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBidXNfcmV2b2x1dGlvbl9wYWxldHRlKGxlbmd0aCh1bmlxdWUoZGF0X3RyaXBfYnlfbW9kZSRtb2RlKSkpKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChtb2RlX3NoYXJlLCAiJSAoIiwgbW9kZV9jb3VudCwgIiB0cmlwcykiKSksCiAgICAgICAgICAgIHZqdXN0ID0gLTAuNSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMi41KSArCiAgbGFicyh0aXRsZSA9ICJNb2RlIFNoYXJlIGJ5IFRyYW5zaXQgVHlwZSIsCiAgICAgICB4ID0gIk1vZGUiLAogICAgICAgeSA9ICJNb2RlIFNoYXJlICglKSIsCiAgICAgICBmaWxsID0gIk1vZGUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCgojIyMgVW5yYXZlbGluZyB0aGUgRGlzcGFyaXRpZXMgaW4gQnVzIFNlcnZpY2UgRWZmaWNpZW5jeQoKVGhlIGRpc3Bhcml0aWVzIGluIGJ1cyBzZXJ2aWNlIGVmZmljaWVuY3kgYmV0d2VlbiB1cmJhbiBhbmQgc3VidXJiYW4gYXJlYXMgYXJlIHN0YXJrbHkgaGlnaGxpZ2h0ZWQgYnkgZnJlcXVlbmN5IGRhdGEuIEluIHN1YnVyYmFuIGFyZWFzLCB0aGUgbWFqb3JpdHkgb2YgYnVzIHN0b3BzIHN1ZmZlciBmcm9tIGluZnJlcXVlbnQgc2VydmljZXMuIFRoaXMgY29udHJhc3RzIHNoYXJwbHkgd2l0aCB1cmJhbiBhcmVhcywgd2hlcmUgYnVzIHN0b3BzIGdlbmVyYWxseSBwcm92aWRlIG1vcmUgZnJlcXVlbnQgc2VydmljZXMuIFRoZXNlIGRpZmZlcmVuY2VzIHVuZGVybGluZSBzaWduaWZpY2FudCBpbmVxdWl0aWVzIGluIHRyYW5zaXQgYWNjZXNzaWJpbGl0eSwgaW1wYWN0aW5nIGRhaWx5IGNvbW11dGVycyBsaWtlIE1pZGdlIHdobyByZWx5IGhlYXZpbHkgb24gdGhlc2Ugc2VydmljZXMuCgpJbiB0aGUgZm9sbG93aW5nIGxlYWZsZXQgbWFwLCB3ZSBpbGx1c3RyYXRlIHRoZXNlIGRpc3Bhcml0aWVzLiBZb3UnbGwgc2VlIHRoYXQgYnVzIHN0b3BzIGluIHN1YnVyYmFuIGFyZWFzIHByZWRvbWluYW50bHkgaGF2ZSBsb25nZXIgd2FpdGluZyB0aW1lcywgPHNwYW4gc3R5bGU9ImNvbG9yOiAjNjU1QkE2OyI+ZXhjZWVkaW5nIDE1IG1pbnV0ZXM8L3NwYW4+LCB3aGVyZWFzIHVyYmFuIHN0b3BzIHR5cGljYWxseSBoYXMgd2FpdGluZyB0aW1lIDxzcGFuIHN0eWxlPSJjb2xvcjogI0E2MTIzQTsiPnVuZGVyIDE1IG1pbnV0ZXM8L3NwYW4+LCBkZW1vbnN0cmF0aW5nIG1vcmUgZnJlcXVlbnQgc2VydmljZXMuIFRoaXMgdmlzdWFsIHJlcHJlc2VudGF0aW9uIGVtcGhhc2l6ZXMgdGhlIHVyZ2VudCBuZWVkIGZvciB0YXJnZXRlZCBpbXByb3ZlbWVudHMgaW4gc3VidXJiYW4gdHJhbnNpdCBzeXN0ZW1zIHRvIGJyaWRnZSB0aGUgZ2FwIGFuZCBlbmhhbmNlIG92ZXJhbGwgc2VydmljZSByZWxpYWJpbGl0eSBhbmQgZWZmaWNpZW5jeS4KCmBgYHtyIHNlcnZpY2UgcGVyaW9kIHN0b3AgZGF0YSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9RkFMU0V9CiMgU0VUIFVQIEFWRVJBR0UgVFJJUCBEQVRBIFBFUiBTRVJWSUNFIFBFUklPRCBGT1IgRUFDSCBCVVMgU1RPUAoKZGF0X3RyaXBfY291bnRfcHJkIDwtIGRhdCAlPiUKICBmaWx0ZXIobW9kZSAlaW4lIGMoIkJ1cyIsICJUcm9sbGV5YnVzIiwgIlRyb2xsZXkiKSkgJT4lCiAgZ3JvdXBfYnkoc3RvcF9pZCwgcGVha19jYXRlZ29yeSwgbW9kZSwgZmluYWxfZGF5X3R5cGUpICU+JQogIHN1bW1hcmlzZSh0cmlwX2NvdW50ID0gbigpLCAKICAgICAgICAgICAgQWxsX1JvdXRlcyA9IHBhc3RlKHVuaXF1ZShyb3V0ZV9pZCksIGNvbGxhcHNlID0gIiwgIiksCiAgICAgICAgICAgIC5ncm91cHMgPSAnZHJvcCcpICU+JQogIG11dGF0ZSgKICAgIGhvdXJzID0gZHVyYXRpb25zW3BlYWtfY2F0ZWdvcnldLAogICAgYXZnX3RyaXBfaHIgPSByb3VuZCh0cmlwX2NvdW50IC8gaG91cnMpCiAgKSAlPiUKICBzZWxlY3QoLWhvdXJzKSAlPiUKICBtdXRhdGUobG9nX2F2Z190cmlwX2hyID0gcm91bmQobG9nMXAoYXZnX3RyaXBfaHIpLCBkaWdpdHMgPSAwKSkgJT4lCiAgbXV0YXRlKG1heF9mcmVxID0gaWZlbHNlKGF2Z190cmlwX2hyID49IDEyLCAiNSBNQVgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKGF2Z190cmlwX2hyID49IDYsICIxMCBNQVgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UgKGF2Z190cmlwX2hyID49IDQsICIxNSBNQVgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGF2Z190cmlwX2hyID49IDIsICIzMCBNQVgiLCAiNjAgTUFYIikpKSkpCgpkYXRfdHJpcF9jb3VudF9wcmQgPC0gbGVmdF9qb2luKGRhdF90cmlwX2NvdW50X3ByZCwgc3RvcHMsIGJ5ID0gInN0b3BfaWQiKQoKZGF0X3RyaXBfY291bnRfcHJkIDwtIHN0X2FzX3NmKGRhdF90cmlwX2NvdW50X3ByZCwgY29vcmRzID0gYygic3RvcF9sb24iLCAic3RvcF9sYXQiKSwgY3JzID0gNDMyNiwgcmVtb3ZlID0gRkFMU0UpCgojIHN1bShkYXRfdHJpcF9jb3VudF9wcmQkdHJpcF9jb3VudCkgICMxOTgwNTA1IDwtIEFsd2F5cyBtYWtlIHN1cmUgeW91IHJldGFpbiB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9uCgpTRVBUQV9yZWdpb25fbWFwIDwtIHN0X3RyYW5zZm9ybShTRVBUQV9yZWdpb25fbWFwLCBzdF9jcnMoZGF0X3RyaXBfY291bnRfaHIpKQpgYGAKCmBgYHtyIGF2ZXJhZ2UgYnVzIGhvdXJseSBtYXhmcmVxLCBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjYWNoZT1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KIyAjIERlZmluZSBjb2xvciBwYWxldHRlCiMgcGFsIDwtIGNvbG9yTnVtZXJpYyhwYWxldHRlID0gdmlyaWRpc0xpdGU6OnZpcmlkaXMoMjU2LCBvcHRpb24gPSAiQyIpLCBkb21haW4gPSBkYXRfdHJpcF9jb3VudF9ociRhdmdfdHJpcF9ocikKCiMgRGVmaW5lIHRoZSBjb2xvciBjb2RlcyBmb3IgYnVzIHJldm9sdXRpb24gYW5kIHJldmVyc2UgdGhlbQpidXNfcmV2b2x1dGlvbl9jb2xvcnMgPC0gcmV2KGMoIiNBNjEyM0EiLCAiIzY1NUJBNiIsICIjMjZBNjk5IiwgIiNGMkFFMkUiLCAiI0YyRTVENSIpKQoKIyBFbnN1cmUgbWF4X2ZyZXEgaXMgYSBmYWN0b3Igd2l0aCBsZXZlbHMgbWF0Y2hpbmcgdGhlIGNvbG9ycwpkYXRfdHJpcF9jb3VudF9ociRtYXhfZnJlcSA8LSBmYWN0b3IoZGF0X3RyaXBfY291bnRfaHIkbWF4X2ZyZXEsIGxldmVscyA9IGMoIjUgTUFYIiwgIjEwIE1BWCIsICIxNSBNQVgiLCAiMzAgTUFYIiwgIjYwIE1BWCIpKQoKIyBEZWZpbmUgdGhlIGNvbG9yIHBhbGV0dGUgZm9yIG1heF9mcmVxCm1heF9mcmVxX2NvbG9ycyA8LSBjKCI1IE1BWCIgPSAiIzRCMDA4MiIsICIxMCBNQVgiID0gIiNGRjQ1MDAiLCAiMTUgTUFYIiA9ICIjQTYxMjNBIiwgIjMwIE1BWCIgPSAiIzI2QTY5OSIsICI2MCBNQVgiID0gIiNGMkFFMkUiKQpwYWxfbWF4X2ZyZXEgPC0gY29sb3JGYWN0b3IocGFsZXR0ZSA9IG1heF9mcmVxX2NvbG9ycywgZG9tYWluID0gZGF0X3RyaXBfY291bnRfaHIkbWF4X2ZyZXEpCgojICMgR2VuZXJhdGUgdGhlIGxpc3QgZm9yIG92ZXJsYXlHcm91cHMgd2l0aCB0aGUgZGVzaXJlZCBvcmRlcgojIG92ZXJsYXlfZ3JvdXBzIDwtIGV4cGFuZC5ncmlkKGZpbmFsX2RheV90eXBlID0gYygiV2Vla2RheSIsICJXZWVrZW5kIiksIHBlYWtfY2F0ZWdvcnkgPSBwZWFrX29yZGVyKSAlPiUKIyAgIG11dGF0ZShncm91cF9uYW1lID0gcGFzdGUoZmluYWxfZGF5X3R5cGUsIHBlYWtfY2F0ZWdvcnksIHNlcCA9ICJfIikpICU+JQojICAgcHVsbChncm91cF9uYW1lKQoKIyAjIENyZWF0ZSB0aGUgbGVhZmxldCBtYXAKIyBtX2F2Z190cmlwX2hyIDwtIGxlYWZsZXQoKSAlPiUKIyAgIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24pICU+JQojICAgYWRkUG9seWdvbnMoZGF0YSA9IFNFUFRBX3JlZ2lvbl9tYXAsIGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMSwgZmlsbCA9IEZBTFNFKSAlPiUKIyAgIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IGRhdF90cmlwX2NvdW50X2hyICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtkYXkiKSwKIyAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAiV2Vla2RheSIsCiMgICAgICAgICAgICAgICAgICAgIGxuZyA9IH5zdG9wX2xvbiwgbGF0ID0gfnN0b3BfbGF0LAojICAgICAgICAgICAgICAgICAgICBjb2xvciA9IH5wYWxfbWF4X2ZyZXEobWF4X2ZyZXEpLAojICAgICAgICAgICAgICAgICAgICByYWRpdXMgPSAxLAojICAgICAgICAgICAgICAgICAgICBvcGFjaXR5ID0gMC44LAojICAgICAgICAgICAgICAgICAgICBwb3B1cCA9IH5wYXN0ZTAoIjxiPlN0b3AgSUQ6PC9iPiAiLCBzdG9wX2lkLCAiPGJyPiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGI+U3RvcCBOYW1lOjwvYj4gIiwgc3RvcF9uYW1lLCAiPGJyPiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGI+QXZnIEJ1c2VzL0hyOjwvYj4gIiwgYXZnX3RyaXBfaHIsICI8YnI+IiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5NYXggRnJlcXVlbmN5OjwvYj4gIiwgbWF4X2ZyZXEsICI8YnI+IiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5BbGwgUm91dGVzOjwvYj4gIiwgQWxsX1JvdXRlcywgIjxicj4iLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxiPkRheSBUeXBlOjwvYj4gIiwgZmluYWxfZGF5X3R5cGUpKSAlPiUKIyAgIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IGRhdF90cmlwX2NvdW50X2hyICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtlbmQiKSwKIyAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAiV2Vla2VuZCIsCiMgICAgICAgICAgICAgICAgICAgIGxuZyA9IH5zdG9wX2xvbiwgbGF0ID0gfnN0b3BfbGF0LAojICAgICAgICAgICAgICAgICAgICBjb2xvciA9IH5wYWxfbWF4X2ZyZXEobWF4X2ZyZXEpLAojICAgICAgICAgICAgICAgICAgICByYWRpdXMgPSAxLAojICAgICAgICAgICAgICAgICAgICBvcGFjaXR5ID0gMC44LAojICAgICAgICAgICAgICAgICAgICBwb3B1cCA9IH5wYXN0ZTAoIjxiPlN0b3AgSUQ6PC9iPiAiLCBzdG9wX2lkLCAiPGJyPiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGI+U3RvcCBOYW1lOjwvYj4gIiwgc3RvcF9uYW1lLCAiPGJyPiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGI+QXZnIEJ1c2VzL0hyOjwvYj4gIiwgYXZnX3RyaXBfaHIsICI8YnI+IiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5NYXggRnJlcXVlbmN5OjwvYj4gIiwgbWF4X2ZyZXEsICI8YnI+IiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8Yj5BbGwgUm91dGVzOjwvYj4gIiwgQWxsX1JvdXRlcywgIjxicj4iLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxiPkRheSBUeXBlOjwvYj4gIiwgZmluYWxfZGF5X3R5cGUpKSAlPiUKIyAgIGFkZExheWVyc0NvbnRyb2woCiMgICAgIG92ZXJsYXlHcm91cHMgPSBjKCJXZWVrZGF5IiwgIldlZWtlbmQiKSwKIyAgICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKQojICAgKSAlPiUKIyAgIGhpZGVHcm91cChjKCJXZWVrZW5kIikpICU+JQojICAgYWRkTGVnZW5kKHBhbCA9IHBhbF9tYXhfZnJlcSwgdmFsdWVzID0gZGF0X3RyaXBfY291bnRfaHIkbWF4X2ZyZXEsIHRpdGxlID0gIk1heCBGcmVxdWVuY3kiLAojICAgICAgICAgICAgIHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IikKIyAKIyBtX2F2Z190cmlwX2hyCmBgYAoKYGBge3IgYXZlcmFnZSBidXMgaG91cmx5IHNpbXBsaWZpZWQsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNhY2hlPUZBTFNFfQojIERlZmluZSBjb2xvciBwYWxldHRlIGZvciBzaW1wbGlmaWVkIGZyZXF1ZW5jeSB1c2luZyB0aGUgYnVzIHJldm9sdXRpb24gY29sb3JzCnBhbCA8LSBjb2xvckZhY3RvcihjKCIjQTYxMjNBIiwgIiM2NTVCQTYiKSwgZG9tYWluID0gYygiMTUgbWludXRlcyBvciBsZXNzIiwgIk1vcmUgdGhhbiAxNSBtaW51dGVzIikpCgojIENyZWF0ZSB0aGUgbGVhZmxldCBtYXAKbV9hdmdfdHJpcF9ociA8LSBsZWFmbGV0KCkgJT4lCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5Qb3NpdHJvbikgJT4lCiAgYWRkUG9seWdvbnMoZGF0YSA9IFNFUFRBX3JlZ2lvbl9tYXAsIGNvbG9yID0gImJsYWNrIiwgd2VpZ2h0ID0gMSwgZmlsbCA9IEZBTFNFKSAlPiUKICBhZGRDaXJjbGVNYXJrZXJzKAogICAgZGF0YSA9IGRhdF90cmlwX2NvdW50X2hyICU+JSBmaWx0ZXIoZmluYWxfZGF5X3R5cGUgPT0gIldlZWtkYXkiICYgIWlzLm5hKGNhdGVnb3J5KSksCiAgICBncm91cCA9IH5jYXRlZ29yeSwgICMgR3JvdXAgZGF0YSBiYXNlZCBvbiB1cmJhbiBvciBzdWJ1cmJhbgogICAgbG5nID0gfnN0b3BfbG9uLCAKICAgIGxhdCA9IH5zdG9wX2xhdCwKICAgIGNvbG9yID0gfnBhbChzaW1wbGlmaWVkX2ZyZXEpLCAgIyBDb2xvciBiYXNlZCBvbiBzaW1wbGlmaWVkIGZyZXF1ZW5jeQogICAgcmFkaXVzID0gMSwKICAgIG9wYWNpdHkgPSAwLjgsCiAgICBwb3B1cCA9IH5wYXN0ZTAoIjxiPlN0b3AgSUQ6PC9iPiAiLCBzdG9wX2lkLCAiPGJyPiIsCiAgICAgICAgICAgICAgICAgICAgIjxiPlN0b3AgTmFtZTo8L2I+ICIsIHN0b3BfbmFtZSwgIjxicj4iLAogICAgICAgICAgICAgICAgICAgICI8Yj5BdmcgQnVzZXMvSHI6PC9iPiAiLCBhdmdfdHJpcF9ociwgIjxicj4iLAogICAgICAgICAgICAgICAgICAgICI8Yj5NYXggRnJlcXVlbmN5OjwvYj4gIiwgc2ltcGxpZmllZF9mcmVxLCAiPGJyPiIsCiAgICAgICAgICAgICAgICAgICAgIjxiPkFsbCBSb3V0ZXM6PC9iPiAiLCBBbGxfUm91dGVzKQogICkgJT4lCiAgYWRkTGF5ZXJzQ29udHJvbCgKICAgIG92ZXJsYXlHcm91cHMgPSBjKCJ1cmJhbiIsICJzdWJ1cmJhbiIpLAogICAgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKQogICkgJT4lCiAgYWRkQ29udHJvbChodG1sID0gIjxkaXYgc3R5bGU9J2JhY2tncm91bmQtY29sb3I6IHdoaXRlOyBwYWRkaW5nOiA1cHg7Jz48c3Ryb25nPlNvdXJjZTo8L3N0cm9uZz4gU0VQVEEgR1RGUyBEYXRhIDIwMjQ8L2Rpdj4iLCBwb3NpdGlvbiA9ICJib3R0b21sZWZ0IikKCiMgRGlzcGxheSB0aGUgbWFwCm1fYXZnX3RyaXBfaHIKCmBgYAoKTWlkZ2XigJlzIGRhaWx5IGNoYWxsZW5nZSB3aXRoIGluY29uc2lzdGVudCBzdWJ1cmJhbiBidXMgc2VydmljZSByZWZsZWN0cyBicm9hZGVyIHRyYW5zaXQgaW5lcXVpdGllcyBiZXR3ZWVuIHVyYmFuIGFuZCBzdWJ1cmJhbiBzZXR0aW5ncy4gVGhpcyBkaXNwYXJpdHkgaXMgZXhlbXBsaWZpZWQgYnkgdGhlIG9wZXJhdGlvbmFsIGluZWZmaWNpZW5jaWVzIG9mIHN1YnVyYmFuIHJvdXRlcywgaGlnaGxpZ2h0ZWQgYnkgZGF0YSBpbmRpY2F0aW5nIHRoZXNlIGJ1c2VzIGZyZXF1ZW50bHkgZmFsbCB3aXRoaW4gdGhlIGxvd2VzdCAxNXRoIHBlcmNlbnRpbGUgZm9yIHNlcnZpY2UgcGVyZm9ybWFuY2UuIFRoaXMgbG93IHBlcmNlbnRpbGUgaW5kaWNhdGVzIHByb2xvbmdlZCB3YWl0IHRpbWVzIGFuZCB1bnJlbGlhYmxlIHNjaGVkdWxlc+KAlGZhY3RvcnMgY29udHJpYnV0aW5nIHRvIGhpZ2hlciBvcGVyYXRpb25hbCBjb3N0cyBhbmQgcmVkdWNlZCByZWxpYWJpbGl0eSBjb21wYXJlZCB0byBtb3JlIGVmZmljaWVudCB1cmJhbiBjb3VudGVycGFydHMuCgo8c3BhbiBzdHlsZT0iY29sb3I6ICM2NTVCQTY7Ij5TdWJ1cmJhbiBidXNlczwvc3Bhbj4sIGxpa2UgdGhlIHJvdXRlcyBNaWRnZSB1c2VzLCBvZnRlbiBzdWZmZXIgZHVlIHRvIGxvd2VyIHJpZGVyc2hpcCBkZW5zaXRpZXMgYW5kIGxlc3Mgb3B0aW1pemVkIHJvdXRlIHBsYW5uaW5nLCBhcyByZWZsZWN0ZWQgaW4gdGhlIHNpZ25pZmljYW50IG51bWJlciBvZiBzdWJ1cmJhbiByb3V0ZXMgbGlrZSBSb3V0ZXMgMTE4LCAxMjksIGFuZCA5MCB1bmRlcnBlcmZvcm1pbmcgaW4gdGhlIDE1dGggcGVyY2VudGlsZS4gVGhlc2Ugcm91dGVzJyBpbmVmZmljaWVuY2llcyBzdGFya2x5IGNvbnRyYXN0IHdpdGggdGhlIHJvYnVzdCB0cmFuc2l0IHN5c3RlbXMgaW4gdXJiYW4gYXJlYXMsIHVuZGVyc2NvcmluZyBhIGNyaXRpY2FsIGdhcCBpbiB0cmFuc2l0IGVxdWl0eSBhbmQgZWZmaWNpZW5jeSB0aGF0IGRlbWFuZHMgaW5ub3ZhdGl2ZSBzb2x1dGlvbnMuCgpgYGB7ciBzY2F0dGVycGxvdCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgY2FjaGU9RkFMU0V9Cgpyb3V0ZV9ldmFsdWF0aW9uIDwtIHJlYWQuY3N2KCJkYXRhL3JvdXRlX2V2YWx1YXRpb25fcmVwb3J0XzIwMTkuY3N2Iiwgc2VwID0gIjsiKQoKIyBDb252ZXJ0IENvc3QucGVyLlBhc3NlbmdlciBhbmQgUGFzc2VuZ2Vycy5wZXIuUmV2ZW51ZS5Ib3VyIGludG8gcHJvcGVyIG51bWVyaWMgY29sdW1ucwpyb3V0ZV9ldmFsdWF0aW9uJENvc3QucGVyLlBhc3NlbmdlciA8LSBhcy5udW1lcmljKGdzdWIoIlskLF0iLCAiIiwgcm91dGVfZXZhbHVhdGlvbiRDb3N0LnBlci5QYXNzZW5nZXIpKQpyb3V0ZV9ldmFsdWF0aW9uJFBhc3NlbmdlcnMucGVyLlJldmVudWUuSG91ciA8LSBhcy5udW1lcmljKHJvdXRlX2V2YWx1YXRpb24kUGFzc2VuZ2Vycy5wZXIuUmV2ZW51ZS5Ib3VyKQoKIyBDYWxjdWxhdGUgMTV0aCBwZXJjZW50aWxlIGZvciBQYXNzZW5nZXJzIGFuZCA4NXRoIHBlcmNlbnRpbGUgZm9yIENvc3QgKGR1ZSB0byByZXZlcnNlZCBheGlzKQpwYXNzZW5nZXJfMTV0aCA8LSBxdWFudGlsZShyb3V0ZV9ldmFsdWF0aW9uJFBhc3NlbmdlcnMucGVyLlJldmVudWUuSG91ciwgcHJvYnMgPSAwLjE1LCBuYS5ybSA9IFRSVUUpCmNvc3RfODV0aCA8LSBxdWFudGlsZShyb3V0ZV9ldmFsdWF0aW9uJENvc3QucGVyLlBhc3NlbmdlciwgcHJvYnMgPSAwLjg1LCBuYS5ybSA9IFRSVUUpCgojIERlZmluZSBjb2xvciBwYWxldHRlIGZvciB0aGUgdHlwZXMgb2YgYnVzZXMKcm91dGVfY29sb3JzIDwtIGMoIkNpdHkgQnVzIiA9ICIjQTYxMjNBIiwgIlN1YnVyYmFuIEJ1cyIgPSAiIzY1NUJBNiIpCnBhbCA8LSBjb2xvckZhY3Rvcihyb3V0ZV9jb2xvcnMsIGRvbWFpbiA9IHVuaXF1ZShyb3V0ZV9ldmFsdWF0aW9uJFR5cGUpKQoKIyBDcmVhdGUgdGhlIGdncGxvdApwIDwtIGdncGxvdChyb3V0ZV9ldmFsdWF0aW9uLCBhZXMoeCA9IFBhc3NlbmdlcnMucGVyLlJldmVudWUuSG91ciwgeSA9IENvc3QucGVyLlBhc3NlbmdlciwgY29sb3IgPSBUeXBlLCB0ZXh0ID0gcGFzdGUoIlJvdXRlOiIsIFJvdXRlLCAiPGJyPlBhc3NlbmdlcnMgcGVyIFJldmVudWUgSG91cjoiLCBQYXNzZW5nZXJzLnBlci5SZXZlbnVlLkhvdXIsICI8YnI+Q29zdCBwZXIgUGFzc2VuZ2VyOiIsIENvc3QucGVyLlBhc3NlbmdlciwgIjxicj5UeXBlOiIsIFR5cGUpKSkgKwogIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDAsIHhtYXggPSBwYXNzZW5nZXJfMTV0aCwgeW1pbiA9IG1heChyb3V0ZV9ldmFsdWF0aW9uJENvc3QucGVyLlBhc3NlbmdlciksIHltYXggPSBjb3N0Xzg1dGgsIGZpbGwgPSAibGlnaHRjb3JhbCIsIGFscGhhID0gMC4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gcGFzc2VuZ2VyXzE1dGgsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImdyZXkiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gY29zdF84NXRoLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5IikgKwogIGdlb21fcG9pbnQoKSArCiAgbGFicyh0aXRsZSA9ICJQZXJmb3JtYW5jZSBvZiBTRVBUQSBDaXR5IEJ1cyBhbmQgU3VidXJiYW4gQnVzIiwKICAgICAgIHggPSAiUGFzc2VuZ2VycyBwZXIgUmV2ZW51ZSBIb3VyIiwKICAgICAgIHkgPSAiQ29zdCBwZXIgUGFzc2VuZ2VyIiwKICAgICAgIGNhcHRpb24gPSAiU291cmNlOiBTRVBUQSBGWSAyMDE5IFJlcG9ydCIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gcm91dGVfY29sb3JzKSArCiAgc2NhbGVfeV9yZXZlcnNlKGJyZWFrcyA9IHNlcSgwLCBtYXgocm91dGVfZXZhbHVhdGlvbiRDb3N0LnBlci5QYXNzZW5nZXIsIG5hLnJtID0gVFJVRSksIGJ5ID0gMSksCiAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGRvbGxhcl9mb3JtYXQocHJlZml4ID0gIiQiLCBzdWZmaXggPSAiIiwgYWNjdXJhY3kgPSAwLjAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHJvdXRlX2V2YWx1YXRpb24kUGFzc2VuZ2Vycy5wZXIuUmV2ZW51ZS5Ib3VyLCBuYS5ybSA9IFRSVUUpLCBieSA9IDEwKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gcGFzc2VuZ2VyXzE1dGggLyAyLCB5ID0gNi41LCBsYWJlbCA9ICIxNXRoIHBlcmNlbnRpbGUiLCBzaXplID0gMywgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNSkKCiMgQ29udmVydCB0byBwbG90bHkgZm9yIGFuIGludGVyYWN0aXZlIHBsb3Qgd2l0aCBkZXRhaWxlZCBob3ZlciBpbmZvcm1hdGlvbgpwX3Bsb3RseSA8LSBnZ3Bsb3RseShwLCB0b29sdGlwID0gInRleHQiKQoKIyBEaXNwbGF5IHRoZSBpbnRlcmFjdGl2ZSBwbG90CnBfcGxvdGx5CgpgYGAKCkFsdGhvdWdoIG1pY3JvdHJhbnNpdCBoYXMgYmVlbiBwcm9wb3NlZCBhcyBhbiBhbHRlcm5hdGl2ZSB0byBhZGRyZXNzIHRoZXNlIGluZWZmaWNpZW5jaWVzIGJ5IG9mZmVyaW5nIG1vcmUgYWRhcHRhYmxlIGFuZCBwb3RlbnRpYWxseSBlZmZpY2llbnQgc2VydmljZXMgaW4gbG93ZXItZGVuc2l0eSBhcmVhcywgaXRzIGVmZmVjdGl2ZW5lc3MgcmVtYWlucyBxdWVzdGlvbmFibGUuIEZvciBleGFtcGxlLCBBQyBUcmFuc2l0J3MgZXhwZXJpbWVudCBpbiBPYWtsYW5kIHRvIHJlcGxhY2UgZml4ZWQgcm91dGVzIHdpdGggbWljcm90cmFuc2l0IHJlc3VsdGVkIGluIGEgY29zdCBwZXIgcGFzc2VuZ2VyIHRoYXQgbW9yZSB0aGFuIGRvdWJsZWQsIGhpZ2hsaWdodGluZyB0aGUgY2hhbGxlbmdlcyBvZiBpbXBsZW1lbnRpbmcgc3VjaCBzZXJ2aWNlcyBlZmZlY3RpdmVseS5bXjldCgpUaGlzIGRhdGEgaWxsdXN0cmF0ZXMgdGhhdCB3aGlsZSBtaWNyb3RyYW5zaXQgaXMgb2Z0ZW4gdG91dGVkIGFzIGEgbW9kZXJuIHNvbHV0aW9uIGZvciBkZWNsaW5pbmcgcmlkZXJzaGlwLCBpdCBnZW5lcmFsbHkgZG9lcyBub3QgcGVyZm9ybSBhcyBlZmZpY2llbnRseSBhcyB0cmFkaXRpb25hbCBmaXhlZC1yb3V0ZSBzZXJ2aWNlcy4gVGhlIGNvcmUgZWZmaWNpZW5jeSBvZiBmaXhlZC1yb3V0ZSB0cmFuc2l0IGNvbWVzIGZyb20gaXRzIGFiaWxpdHkgdG8gY29uc29saWRhdGUgcmlkZXJzIGFsb25nIGEgcHJlZGljdGFibGUgcGF0aCwgbWluaW1pemluZyBkZXZpYXRpb25zIGFuZCBlbnN1cmluZyBjb25zaXN0ZW50IHRyYXZlbCB0aW1lcy4gSW4gY29udHJhc3QsIG1pY3JvdHJhbnNpdCdzIG9uLWRlbWFuZCBuYXR1cmUgY2FuIGxlYWQgdG8gc2lnbmlmaWNhbnQgaW5lZmZpY2llbmNpZXMsIHdpdGggcm91dGVzIGNvbnN0YW50bHkgY2hhbmdpbmcgdG8gYWNjb21tb2RhdGUgaW5kaXZpZHVhbCBwaWNrdXAgcmVxdWVzdHMsIGxlYWRpbmcgdG8gaW5jcmVhc2VkIHRyYXZlbCB0aW1lcyBhbmQgb3BlcmF0aW9uYWwgY29zdHMuCgpHaXZlbiB0aGVzZSBjaGFsbGVuZ2VzLCBpdCBtaWdodCBiZSBtb3JlIHBydWRlbnQgdG8gZXhwbG9yZSBvdGhlciBhbHRlcm5hdGl2ZXMsIHN1Y2ggYXMgZGVwbG95aW5nIHNtYWxsZXIsIGZpeGVkLXJvdXRlIG1pbmlidXNzZXMgZHVyaW5nIHBlYWsgaG91cnMgdG8gZW5oYW5jZSBjb25uZWN0aXZpdHkgYW5kIG1hbmFnZSBjcm93ZGluZyBtb3JlIGVmZmVjdGl2ZWx5LiBUaGlzIGFwcHJvYWNoIGNvdWxkIGxldmVyYWdlIHRoZSBsb3dlciBvcGVyYXRpb25hbCBjb3N0cyBvZiBzbWFsbGVyIHZlaGljbGVzIHdoaWxlIG1haW50YWluaW5nIHRoZSBzdHJ1Y3R1cmVkIGVmZmljaWVuY3kgb2YgZml4ZWQtcm91dGUgdHJhbnNpdCwgcG90ZW50aWFsbHkgb2ZmZXJpbmcgYSBtb3JlIHN1c3RhaW5hYmxlIHNvbHV0aW9uIHRvIHRoZSBzdWJ1cmJhbiB0cmFuc2l0IHdvZXMgdGhhdCBNaWRnZSBhbmQgY291bnRsZXNzIG90aGVycyBmYWNlIGRhaWx5LgoKW145XTogW1VyZ28gMjAxOV0oaHR0cHM6Ly93d3cuYXB0YS5jb20vd3AtY29udGVudC91cGxvYWRzL0NvbmZlcmVuY2VzX01lZXRpbmdzX0V2ZW50cy9QcmVzZW50YXRpb25zLzIwMTgtU3VzdGFpbmFiaWxpdHkvVXJnby1Kb2huLnBkZiNwYWdlPTI0KQoKYGBge3Igc3RhdGljIHNjYXR0ZXJwbG90LCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojICMgQXNzdW1pbmcgcGFzc2VuZ2VyXzE1dGggYW5kIGNvc3RfODV0aCBhcmUgeW91ciBjYWxjdWxhdGVkIDE1dGggcGVyY2VudGlsZSB2YWx1ZXMKIyBnZ3Bsb3Qocm91dGVfZXZhbHVhdGlvbiwgYWVzKHggPSBQYXNzZW5nZXJzLnBlci5SZXZlbnVlLkhvdXIsIHkgPSBDb3N0LnBlci5QYXNzZW5nZXIsIGNvbG9yID0gVHlwZSkpICsKIyAgICMgQWRkIGEgcmVjdGFuZ2xlIGFuZCB0ZXh0IGFubm90YXRpb24gZm9yIHRoZSAxNXRoIHBlcmNlbnRpbGUKIyAgIGFubm90YXRlKCJyZWN0IiwgeG1pbiA9IDAsIHhtYXggPSBwYXNzZW5nZXJfMTV0aCwgeW1pbiA9IG1heChyb3V0ZV9ldmFsdWF0aW9uJENvc3QucGVyLlBhc3NlbmdlciksIHltYXggPSBjb3N0Xzg1dGgsCiMgICAgICAgICAgICBmaWxsID0gInJlZCIsIGFscGhhID0gMC4yKSArCiMgICBnZW9tX3BvaW50KCkgKwojICAgbGFicyh0aXRsZSA9ICJQZXJmb3JtYW5jZSBvZiBTRVBUQSBDaXR5IEJ1cyBhbmQgU3VidXJiYW4gQnVzIiwKIyAgICAgICAgeCA9ICJQYXNzZW5nZXJzIHBlciBSZXZlbnVlIEhvdXIiLAojICAgICAgICB5ID0gIkNvc3QgcGVyIFBhc3NlbmdlciIpICsKIyAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSArCiMgICBzY2FsZV95X3JldmVyc2UoYnJlYWtzID0gc2VxKDAsIG1heChyb3V0ZV9ldmFsdWF0aW9uJENvc3QucGVyLlBhc3NlbmdlciwgbmEucm0gPSBUUlVFKSwgYnkgPSAxKSwKIyAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBkb2xsYXJfZm9ybWF0KHByZWZpeCA9ICIkIiwgc3VmZml4ID0gIiIsIGFjY3VyYWN5ID0gMC4wMSkpICsKIyAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgbWF4KHJvdXRlX2V2YWx1YXRpb24kUGFzc2VuZ2Vycy5wZXIuUmV2ZW51ZS5Ib3VyLCBuYS5ybSA9IFRSVUUpLCBieSA9IDEwKSkgKwojICAgdGhlbWVfbWluaW1hbCgpICsKIyAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IHBhc3Nlbmdlcl8xNXRoLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5IikgKwojICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gY29zdF84NXRoLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5IikgKwojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwojICAgYW5ub3RhdGUoInRleHQiLCB4ID0gcGFzc2VuZ2VyXzE1dGggLyAyLCB5ID0gNi41LCBsYWJlbCA9ICIxNXRoIHBlcmNlbnRpbGUiLAojICAgICAgICAgICAgc2l6ZSA9IDMsIGNvbG9yID0gImJsYWNrIikKYGBgCgoKIyMjIEltcGFjdCBhbmQgSW5ub3ZhdGlvbjogRW5oYW5jaW5nIFN1YnVyYmFuIEJ1cyBTZXJ2aWNlcwoKV2hpbGUgdGhlIHJhdyBkYXRhIGlsbHVtaW5hdGVzIHRoZSBzZXJ2aWNlIGRpc3Bhcml0aWVzLCB0aGUgdHJ1ZSBkZXB0aCBvZiB0aGlzIGlzc3VlIGlzIGJlc3QgY2FwdHVyZWQgdGhyb3VnaCB0aGUgbGl2ZWQgZXhwZXJpZW5jZXMgb2Ygc3VidXJiYW4gY29tbXV0ZXJzIGxpa2UgTWlkZ2UuIFBlcnNvbmFsIHN0b3JpZXMgcmV2ZWFsIHRoZSBicm9hZGVyIGh1bWFuIGltcGFjdDogbWlzc2VkIG9wcG9ydHVuaXRpZXMsIHByb2xvbmdlZCB3b3JrZGF5cywgYW5kIGRpbWluaXNoZWQgZmFtaWx5IGxpZmUgZHVlIHRvIGluZnJlcXVlbnQgYnVzIHNlcnZpY2VzLiBUaGlzIHF1YWxpdGF0aXZlIGluc2lnaHQgcGFpbnRzIGEgdml2aWQgcGljdHVyZSBvZiB0aGUgZGFpbHkgY2hhbGxlbmdlcyBhbmQgdW5kZXJzY29yZXMgdGhlIHVyZ2VuY3kgZm9yIHRhcmdldGVkIGltcHJvdmVtZW50cy4KClNFUFRBJ3Mgb25nb2luZyAiQnVzIFJldm9sdXRpb24iIHByb2plY3QgYWltcyB0byBtb2Rlcm5pemUgYW5kIGVuaGFuY2UgYnVzIHNlcnZpY2VzLCBwcm9taXNpbmcgdXBkYXRlZCByb3V0ZXMgYW5kIGltcHJvdmVkIGZyZXF1ZW5jaWVzIHRoYXQgaGF2ZW4ndCBiZWVuIHJldmlzZWQgc2luY2UgdGhlIDE5NjBzLiBXaGlsZSB0aGUgaW5pdGlhdGl2ZSBzZWVrcyB0byByZWR1Y2UgaGVhZHdheXMgdG8gYSBtYXhpbXVtIG9mIDMwIG1pbnV0ZXMgZXZlbiBpbiB0aGUgbW9zdCByZW1vdGUgc3VidXJiYW4gYXJlYXMsIGl0IGhhcyBmYWNlZCBkZWxheXMgYW5kIGNyaXRpY2lzbSwgcGFydGljdWxhcmx5IGNvbmNlcm5pbmcgaXRzIHBvdGVudGlhbCB0byBkaXNwcm9wb3J0aW9uYXRlbHkgaW1wYWN0IGxvdy1pbmNvbWUgbmVpZ2hib3Job29kcy4gVGhpcyB0ZW5zaW9uIGhpZ2hsaWdodHMgdGhlIGNvbXBsZXggaW50ZXJwbGF5IGJldHdlZW4gaW1wcm92aW5nIHNlcnZpY2UgZWZmaWNpZW5jeSBhbmQgYWRkcmVzc2luZyBjb21tdW5pdHkgY29uY2VybnMgb2YgZ2VudHJpZmljYXRpb24uCgpBcyB3ZSBjb25jbHVkZSBvdXIgZXhwbG9yYXRpb24gb2Ygc3VidXJiYW4gYnVzIHRyYW5zaXQgZGlzcGFyaXRpZXMgaW4gUGhpbGFkZWxwaGlhLCB0aGUgY29tcGVsbGluZyBuYXJyYXRpdmVzIG9mIGRhaWx5IGNvbW11dGVycywgdW5kZXJwaW5uZWQgYnkgcm9idXN0IFNFUFRBIGRhdGEsIHBhaW50IGEgY2xlYXIgcGljdHVyZSBvZiB0aGUgY2hhbGxlbmdlcyBhbmQgdGhlIHVyZ2VudCBuZWVkIGZvciBzeXN0ZW1pYyBpbXByb3ZlbWVudHMuIFRoZSAiQnVzIFJldm9sdXRpb24iIHByb2plY3QsIHdoaWxlIGEgcHJvbWlzaW5nIHN0ZXAgdG93YXJkIGVuaGFuY2luZyBidXMgZnJlcXVlbmNpZXMgYW5kIHVwZGF0aW5nIGRlY2FkZXMtb2xkIHJvdXRlcywgYWxzbyBoaWdobGlnaHRzIHRoZSBkZWxpY2F0ZSBiYWxhbmNlIHJlcXVpcmVkIHRvIGltcHJvdmUgc2VydmljZSBlZmZpY2llbmN5IHdpdGhvdXQgZXhhY2VyYmF0aW5nIHNvY2lhbCBpbmVxdWl0aWVzLgoKRW1icmFjaW5nIGlubm92YXRpdmUgc29sdXRpb25zIGFuZCBmb3N0ZXJpbmcgY29tbXVuaXR5IGVuZ2FnZW1lbnQgaW4gdHJhbnNpdCBwbGFubmluZyBhcmUgY3J1Y2lhbC4gQnkgY29tbWl0dGluZyB0byBib3RoIHRlY2hub2xvZ2ljYWwgdXBncmFkZXMgYW5kIGVxdWl0YWJsZSBzZXJ2aWNlIGRpc3RyaWJ1dGlvbiwgU0VQVEEgY2FuIGVuc3VyZSB0aGF0IGV2ZXJ5IGNvbW11dGVyLCByZWdhcmRsZXNzIG9mIHdoZXJlIHRoZXkgbGl2ZSwgaGFzIHJlbGlhYmxlIGFuZCB0aW1lbHkgYWNjZXNzIHRvIHB1YmxpYyB0cmFuc2l0LiBUaGlzIG5vdCBvbmx5IGltcHJvdmVzIGluZGl2aWR1YWwgZGFpbHkgZXhwZXJpZW5jZXMgYnV0IGFsc28gc3VwcG9ydHMgYnJvYWRlciBnb2FscyBvZiBlY29ub21pYyBtb2JpbGl0eSBhbmQgc3VzdGFpbmFibGUgdXJiYW4gZGV2ZWxvcG1lbnQuCgpBcyBzdGFrZWhvbGRlcnMsIHdlIGFyZSBjYWxsZWQgdXBvbiB0byBzdXBwb3J0IHRoZXNlIGluaXRpYXRpdmVzLCBhZHZvY2F0ZSBmb3IgdHJhbnNwYXJlbnQgYW5kIGluY2x1c2l2ZSBwbGFubmluZyBwcm9jZXNzZXMsIGFuZCBlbnN1cmUgdGhhdCB0aGUgdm9pY2VzIG9mIGFsbCBjb21tdXRlcnMsIGVzcGVjaWFsbHkgdGhvc2UgbW9zdCBhZmZlY3RlZCBsaWtlIE1pZGdlLCBhcmUgaGVhcmQgYW5kIGFkZHJlc3NlZCBpbiB0aGUgcHVyc3VpdCBvZiBhIHRydWx5IGNvbm5lY3RlZCBhbmQgZXF1aXRhYmxlIHRyYW5zaXQgc3lzdGVtLg==